Single backtick now used for all code quotes.
This commit is contained in:
parent
04b98a3786
commit
4cac382581
112
docs/usage.md
112
docs/usage.md
|
@ -22,37 +22,37 @@ The 7 SEGMENT.TTF font from the docs directory is needed for simulating 7 segmen
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
OpenSCAD has to be setup to find libraries by setting the ```OPENSCADPATH``` environment variable to where you want to file your libraries and NopSCADlib needs to be installed
|
OpenSCAD has to be setup to find libraries by setting the `OPENSCADPATH` environment variable to where you want to file your libraries and NopSCADlib needs to be installed
|
||||||
in the directory it points to. This can be done with ```git clone https://github.com/nophead/NopSCADlib.git``` while in that directory or, if you don't want to use GIT,
|
in the directory it points to. This can be done with `git clone https://github.com/nophead/NopSCADlib.git` while in that directory or, if you don't want to use GIT,
|
||||||
by downloading https://github.com/nophead/NopSCADlib/archive/master.zip and unzipping it to a directory called NopSCADlib.
|
by downloading https://github.com/nophead/NopSCADlib/archive/master.zip and unzipping it to a directory called NopSCADlib.
|
||||||
|
|
||||||
The ```NopSCADlib/scripts``` directory needs to be added to the executable search path, ```PATH``` on Windows and ```path``` on Linux and Mac.
|
The `NopSCADlib/scripts` directory needs to be added to the executable search path, `PATH` on Windows and `path` on Linux and Mac.
|
||||||
|
|
||||||
The installation can be tested by opening ```NopSCADlib/libtest.scad``` in the OpenSCAD GUI. It should render all the objects in the library in about 1 minute.
|
The installation can be tested by opening `NopSCADlib/libtest.scad` in the OpenSCAD GUI. It should render all the objects in the library in about 1 minute.
|
||||||
|
|
||||||
Running ```tests``` from the command line will run all the tests in the ```tests``` directory and build the ```readme.md``` catalog for GitHub and render it to ```readme.html```
|
Running `tests` from the command line will run all the tests in the `tests` directory and build the `readme.md` catalog for GitHub and render it to `readme.html`
|
||||||
for local preview.
|
for local preview.
|
||||||
|
|
||||||
## Directory structure
|
## Directory structure
|
||||||
|
|
||||||
| Path | Contents |
|
| Path | Contents |
|
||||||
|:-----|:------|
|
|:-----|:------|
|
||||||
| ```NopSCADlib``` | Top level scad files, e.g. ```lib.scad``` |
|
| `NopSCADlib` | Top level scad files, e.g. `lib.scad` |
|
||||||
| ```NopSCADlib/doc``` | Documentation like this that is not automatically generated |
|
| `NopSCADlib/doc` | Documentation like this that is not automatically generated |
|
||||||
| ```NopSCADlib/examples``` | Example projects |
|
| `NopSCADlib/examples` | Example projects |
|
||||||
| ```NopSCADlib/gallery``` | Pictures of items that have been made with the library |
|
| `NopSCADlib/gallery` | Pictures of items that have been made with the library |
|
||||||
| ```NopSCADlib/printed``` | Scad files for making reusable printed parts |
|
| `NopSCADlib/printed` | Scad files for making reusable printed parts |
|
||||||
| ```NopSCADlib/scripts``` | Python scripts |
|
| `NopSCADlib/scripts` | Python scripts |
|
||||||
| ```NopSCADlib/tests``` | A stand alone test for each type of vitamin and most of the utilities |
|
| `NopSCADlib/tests` | A stand alone test for each type of vitamin and most of the utilities |
|
||||||
| ```NopSCADlib/utils``` | Utility scad files |
|
| `NopSCADlib/utils` | Utility scad files |
|
||||||
| ```NopSCADlib/utils/core``` | Core utilities used by nearly everything |
|
| `NopSCADlib/utils/core` | Core utilities used by nearly everything |
|
||||||
| ```NopSCADlib/vitamins``` | Generally a pair of .scad files for each type of vitamin. The plural version contains object definitions to be included and it uses the singular version. |
|
| `NopSCADlib/vitamins` | Generally a pair of .scad files for each type of vitamin. The plural version contains object definitions to be included and it uses the singular version. |
|
||||||
|
|
||||||
|
|
||||||
## Making a project
|
## Making a project
|
||||||
|
|
||||||
Each project has its own directory and that is used to derive the project's name.
|
Each project has its own directory and that is used to derive the project's name.
|
||||||
There should also be a subdirectory called ```scad``` with a scad file in it that contains the main assembly.
|
There should also be a subdirectory called `scad` with a scad file in it that contains the main assembly.
|
||||||
A skeleton project looks like this: -
|
A skeleton project looks like this: -
|
||||||
|
|
||||||
//! Project description in Markdown format before the first include.
|
//! Project description in Markdown format before the first include.
|
||||||
|
@ -72,30 +72,30 @@ A skeleton project looks like this: -
|
||||||
|
|
||||||
Other scad files can be added to the scad directory and included or used as required.
|
Other scad files can be added to the scad directory and included or used as required.
|
||||||
|
|
||||||
* Subassemblies can be added in the same format as ```main_assembly()```, i.e. a module called ```something_assembly()```, taking no parameters and calling ```assembly("something")```
|
* Subassemblies can be added in the same format as `main_assembly()`, i.e. a module called `something_assembly()`, taking no parameters and calling `assembly("something")`
|
||||||
with the rest of its contents passed as children.
|
with the rest of its contents passed as children.
|
||||||
It needs to be called directly or indirectly from ```main_assembly()``` to appear in the view and on the BOM.
|
It needs to be called directly or indirectly from `main_assembly()` to appear in the view and on the BOM.
|
||||||
Assembly instructions should be added directly before the module definition in comments marked with ```//!```.
|
Assembly instructions should be added directly before the module definition in comments marked with `//!`.
|
||||||
|
|
||||||
* Any printed parts should be made by a module called ```something_stl()```, taking no parameters and calling ```stl("something")``` so they appear on the BOM when called from
|
* Any printed parts should be made by a module called `something_stl()`, taking no parameters and calling `stl("something")` so they appear on the BOM when called from
|
||||||
an assembly. Printed parts are usually ```color```ed and ```render```ed at the point they are used in the assembly.
|
an assembly. Printed parts are usually `color`ed and `render`ed at the point they are used in the assembly.
|
||||||
|
|
||||||
* Any 2D routed parts should be made by a module called ```something_dxf()```, taking no parameters and calling ```dxf("something")``` so they appear on the BOM when called from an
|
* Any 2D routed parts should be made by a module called `something_dxf()`, taking no parameters and calling `dxf("something")` so they appear on the BOM when called from an
|
||||||
assembly. They are generally made from a ```sheet_2D()``` with holes subtracted from it. That will also put the sheet material on the BOM.
|
assembly. They are generally made from a `sheet_2D()` with holes subtracted from it. That will also put the sheet material on the BOM.
|
||||||
They are then expanded to 3D using ```render_2D_sheet()``` when they are placed in an assembly.
|
They are then expanded to 3D using `render_2D_sheet()` when they are placed in an assembly.
|
||||||
|
|
||||||
When ```make_all``` is run from the top level directory of the project it will create the following sub-directories and populate them:-
|
When `make_all` is run from the top level directory of the project it will create the following sub-directories and populate them:-
|
||||||
|
|
||||||
| Directory | Contents |
|
| Directory | Contents |
|
||||||
|:----------|:---------|
|
|:----------|:---------|
|
||||||
| assemblies | For each assembly: an assembled view and an exploded assembly view, in large and small formats |
|
| assemblies | For each assembly: an assembled view and an exploded assembly view, in large and small formats |
|
||||||
| bom | A flat BOM in ```bom.txt``` for the whole project, flat BOMs in text format for each assembly and a hierarchical BOM in JSON format: ```bom.json```.|
|
| bom | A flat BOM in `bom.txt` for the whole project, flat BOMs in text format for each assembly and a hierarchical BOM in JSON format: `bom.json`.|
|
||||||
| deps | Dependency files for each scad file in the project, so that subsequent builds can be incremental |
|
| deps | Dependency files for each scad file in the project, so that subsequent builds can be incremental |
|
||||||
| dxfs | DXF files for all the CNC routed parts in the project and small PNG images of them |
|
| dxfs | DXF files for all the CNC routed parts in the project and small PNG images of them |
|
||||||
| stls | STL files for all the printed parts in the project and small PNG images of them |
|
| stls | STL files for all the printed parts in the project and small PNG images of them |
|
||||||
|
|
||||||
It will also make a Markdown assembly manual called ```readme.md``` suitable for GitHub, a version rendered to HTML for viewing locally called ```readme.html``` and a second
|
It will also make a Markdown assembly manual called `readme.md` suitable for GitHub, a version rendered to HTML for viewing locally called `readme.html` and a second
|
||||||
HTML version called ```printme.html```. This has page breaks instead of horizontal rules between sections and can be converted to PDF using Chrome to make a stand alone manual.
|
HTML version called `printme.html`. This has page breaks instead of horizontal rules between sections and can be converted to PDF using Chrome to make a stand alone manual.
|
||||||
|
|
||||||
Each time OpenSCAD is run to produce STL files, DXF files or assembly views, the time it takes is recorded and compared with the previous time.
|
Each time OpenSCAD is run to produce STL files, DXF files or assembly views, the time it takes is recorded and compared with the previous time.
|
||||||
At the end the times are printed with the delta from the last run and coloured red or green if they have got significantly faster or slower.
|
At the end the times are printed with the delta from the last run and coloured red or green if they have got significantly faster or slower.
|
||||||
|
@ -112,7 +112,7 @@ All the vitamins and utilities are included if you include [NopSCADlib/lib.scad]
|
||||||
Printed parts are not included and need to be used or included explicitly, their documentation states which files need to be included rather than used.
|
Printed parts are not included and need to be used or included explicitly, their documentation states which files need to be included rather than used.
|
||||||
|
|
||||||
This is the easiest way to use the library and is reasonably efficient because the only files included are the object list definitions, all the functions and modules are used, so
|
This is the easiest way to use the library and is reasonably efficient because the only files included are the object list definitions, all the functions and modules are used, so
|
||||||
get shared if other files in the project include ```lib.scad``` as well, or if you have multiple projects open in the same instance of OpenSCAD.
|
get shared if other files in the project include `lib.scad` as well, or if you have multiple projects open in the same instance of OpenSCAD.
|
||||||
|
|
||||||
One downside is that any change to the library will mean all the project files need regenerating.
|
One downside is that any change to the library will mean all the project files need regenerating.
|
||||||
A more optimised approach for large projects is to include [NopSCADlib/core.scad](../core.scad) instead.
|
A more optimised approach for large projects is to include [NopSCADlib/core.scad](../core.scad) instead.
|
||||||
|
@ -123,17 +123,17 @@ Any other vitamins used need to be included explicitly. One can copy the include
|
||||||
|
|
||||||
Modules that generate parts and assemblies need to take no parameters so that they can be called from the framework to make the STL files and assembly views, etc.
|
Modules that generate parts and assemblies need to take no parameters so that they can be called from the framework to make the STL files and assembly views, etc.
|
||||||
Sometimes parts or asemblies need to be parametric, for example fan guards take the fan as a parameter.
|
Sometimes parts or asemblies need to be parametric, for example fan guards take the fan as a parameter.
|
||||||
To work around this the ```fan_guard()``` module calls the ```stl()``` module with a variable name which has a suffix of the fan width, e.g. "fan_guard_60".
|
To work around this the `fan_guard()` module calls the `stl()` module with a variable name which has a suffix of the fan width, e.g. "fan_guard_60".
|
||||||
This ensures that if there are different sized fans in the same project the STL files have unique names.
|
This ensures that if there are different sized fans in the same project the STL files have unique names.
|
||||||
It is then up to the user to add a wrapper to their project called ```fan_guard_60_stl()``` that calls ```fan_guard()``` with a 60mm fan: -
|
It is then up to the user to add a wrapper to their project called `fan_guard_60_stl()` that calls `fan_guard()` with a 60mm fan: -
|
||||||
|
|
||||||
module fan_guard_60_stl() fan_guard(fan60x15);
|
module fan_guard_60_stl() fan_guard(fan60x15);
|
||||||
|
|
||||||
Calling ```fan_guard(fan60x15)``` draws a fan guard for a 60mm fan and puts ```fan_guard_60.stl``` on the BOM. The framework then looks for a module ```fan_guard_60_stl()``` to
|
Calling `fan_guard(fan60x15)` draws a fan guard for a 60mm fan and puts `fan_guard_60.stl` on the BOM. The framework then looks for a module `fan_guard_60_stl()` to
|
||||||
generate it.
|
generate it.
|
||||||
|
|
||||||
This is OK if the fan will always be 60mm but what if the project is parametric and the fan size can vary?
|
This is OK if the fan will always be 60mm but what if the project is parametric and the fan size can vary?
|
||||||
To cater for that ```fan_guard()``` can be passed a ```name``` parameter to name the STL.
|
To cater for that `fan_guard()` can be passed a `name` parameter to name the STL.
|
||||||
For example a 3D printer might have a bed cooling fan and different sized machines might have different size fans.
|
For example a 3D printer might have a bed cooling fan and different sized machines might have different size fans.
|
||||||
|
|
||||||
bed_fan = fan80x38;
|
bed_fan = fan80x38;
|
||||||
|
@ -144,7 +144,7 @@ In this case the STL file has a constant name related to its use, regardless of
|
||||||
|
|
||||||
### Assembly boundaries
|
### Assembly boundaries
|
||||||
|
|
||||||
The ```assembly()``` module is used to mark assemblies that correspond to a step of construction.
|
The `assembly()` module is used to mark assemblies that correspond to a step of construction.
|
||||||
Each assembly named in this way gets a page in the build manual with a list of the parts and sub-assemblies that it uses, an exploded view,
|
Each assembly named in this way gets a page in the build manual with a list of the parts and sub-assemblies that it uses, an exploded view,
|
||||||
some build instructions and then the assembled view.
|
some build instructions and then the assembled view.
|
||||||
This doesn't always correspond with how one would want to structure the code.
|
This doesn't always correspond with how one would want to structure the code.
|
||||||
|
@ -182,26 +182,26 @@ This is achieved by having a pair of modules: -
|
||||||
screw_and_washer(screw, screw_length, true);
|
screw_and_washer(screw, screw_length, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Notice how the first module ```handle_assembly()``` uses ```assembly()``` and has a build instruction. It isn't used directly in a project though, ```handle_fastened_assembly()``` is
|
Notice how the first module `handle_assembly()` uses `assembly()` and has a build instruction. It isn't used directly in a project though, `handle_fastened_assembly()` is
|
||||||
what is actually called from the parent assembly.
|
what is actually called from the parent assembly.
|
||||||
Because it doesn't have a call to ```assembly()```, the fasteners are added to the parent but the STL and the inserts become a sub-assembly.
|
Because it doesn't have a call to `assembly()`, the fasteners are added to the parent but the STL and the inserts become a sub-assembly.
|
||||||
|
|
||||||
When the parent assembly is shown exploded the handle's screws will be exploded but the inserts won't. They only explode when the sub-assembly is shown exloded.
|
When the parent assembly is shown exploded the handle's screws will be exploded but the inserts won't. They only explode when the sub-assembly is shown exloded.
|
||||||
|
|
||||||
Note also the ```pose([225, 0, 150], [0, 0, 14])``` call before the ```assembly()``` call. This allows the sub-assembly to be posed differently in its build step but doesn't
|
Note also the `pose([225, 0, 150], [0, 0, 14])` call before the `assembly()` call. This allows the sub-assembly to be posed differently in its build step but doesn't
|
||||||
affect its orientation in the parent assembly. The pose parameters are the rotation and the translation taken from the GUI.
|
affect its orientation in the parent assembly. The pose parameters are the rotation and the translation taken from the GUI.
|
||||||
|
|
||||||
### Exploded diagrams
|
### Exploded diagrams
|
||||||
|
|
||||||
A lot of vitamins explode themselves when ```$explode=1```. This is done with module ```explode()``` that can be passed a Z offset, or a 3D vector that gives the displacement
|
A lot of vitamins explode themselves when `$explode=1`. This is done with module `explode()` that can be passed a Z offset, or a 3D vector that gives the displacement
|
||||||
and it draws a line from the origial position to the exploded position. The line can be offset from the origin of the component by specifying an offset vector.
|
and it draws a line from the origial position to the exploded position. The line can be offset from the origin of the component by specifying an offset vector.
|
||||||
|
|
||||||
Often user assemblies need to add ```explode()``` in various places to explode printed parts, for example.
|
Often user assemblies need to add `explode()` in various places to explode printed parts, for example.
|
||||||
|
|
||||||
### Creating vitamins
|
### Creating vitamins
|
||||||
|
|
||||||
Most vitamins are parametric and use a named list of properties to describe them is a pseudo OO style.
|
Most vitamins are parametric and use a named list of properties to describe them is a pseudo OO style.
|
||||||
These lists are passed to every function or module related to the vitamin as the first parameter called ```type```.
|
These lists are passed to every function or module related to the vitamin as the first parameter called `type`.
|
||||||
They need to be included in the user code, so that the list names are visible. The functions and modules however only need to be used, not included.
|
They need to be included in the user code, so that the list names are visible. The functions and modules however only need to be used, not included.
|
||||||
|
|
||||||
This leads to a pair of files for each vitamin. One with a plural name that defines the objects and then uses the file with a singular name
|
This leads to a pair of files for each vitamin. One with a plural name that defines the objects and then uses the file with a singular name
|
||||||
|
@ -216,50 +216,50 @@ These functions take a particular form, so they can be scraped out and added to
|
||||||
|
|
||||||
function spring_od(type) = type[1]; //! Outside diameter
|
function spring_od(type) = type[1]; //! Outside diameter
|
||||||
|
|
||||||
Other functions and modules with ```//!``` comments will be added to the documentation as functions and modules.
|
Other functions and modules with `//!` comments will be added to the documentation as functions and modules.
|
||||||
Functions and modules without these special comments are considered private and do not appear in the documentation.
|
Functions and modules without these special comments are considered private and do not appear in the documentation.
|
||||||
|
|
||||||
A vitamin announces itself to the BOM by calling the ```vitamin()``` module with a string description composed of two parts separated by a colon.
|
A vitamin announces itself to the BOM by calling the `vitamin()` module with a string description composed of two parts separated by a colon.
|
||||||
The first part is a string representation of the module instantiation.
|
The first part is a string representation of the module instantiation.
|
||||||
This is used in the documentation to show how to instantiate every part available.
|
This is used in the documentation to show how to instantiate every part available.
|
||||||
To facilitate this the first element in the type list is the name of the list as a string and is simply accessed as ```type[0]```.
|
To facilitate this the first element in the type list is the name of the list as a string and is simply accessed as `type[0]`.
|
||||||
|
|
||||||
The part of the description after the colon is free format text that appears on the BOM. Since vitamins are listed alphabetically starting the description with the broad
|
The part of the description after the colon is free format text that appears on the BOM. Since vitamins are listed alphabetically starting the description with the broad
|
||||||
category of the part and leaving the more refined description to the end generates tidier parts lists.
|
category of the part and leaving the more refined description to the end generates tidier parts lists.
|
||||||
For example ```Screw M3 pan x 30mm``` ensures all the screws appear together and are ordered by their diameter before length, although ```M3 x 30mm pan screw``` would be
|
For example `Screw M3 pan x 30mm` ensures all the screws appear together and are ordered by their diameter before length, although `M3 x 30mm pan screw` would be
|
||||||
more natural.
|
more natural.
|
||||||
|
|
||||||
Vitamins are only ever previewed, so they are optimised to draw quickly in F5 and don't need to worry about being manifold.
|
Vitamins are only ever previewed, so they are optimised to draw quickly in F5 and don't need to worry about being manifold.
|
||||||
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
|
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
|
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.
|
that is cached and reused. This will be very slow the first time it renders but very fast afterwards.
|
||||||
|
|
||||||
### Panels and Platters
|
### Panels and Platters
|
||||||
|
|
||||||
The ```stls``` and ```dxfs``` scripts produce a file for each part but often it is desirable to print or route collections of parts laid out together.
|
The `stls` and `dxfs` scripts produce a file for each part but often it is desirable to print or route collections of parts laid out together.
|
||||||
This can be done by adding scad files to folders called ```platters``` for STL files and ```panels``` for DXF files.
|
This can be done by adding scad files to folders called `platters` for STL files and `panels` for DXF files.
|
||||||
These can aggregate and lay out parts by including ```NopSCADlib/core.scad``` and using modules ```use_stl(name)``` and ```use_dxf(name)```.
|
These can aggregate and lay out parts by including `NopSCADlib/core.scad` and using modules `use_stl(name)` and `use_dxf(name)`.
|
||||||
These modules import the already generated singular STL and DXF files, so they are relatively fast. The name does not include the suffix.
|
These modules import the already generated singular STL and DXF files, so they are relatively fast. The name does not include the suffix.
|
||||||
The scad files typically also need to include other files from the project to get the dimensions of the parts to calculate their positions.
|
The scad files typically also need to include other files from the project to get the dimensions of the parts to calculate their positions.
|
||||||
|
|
||||||
The composite part files have the same name as the scad file that generates them, with the suffix changed to ```.stl``` or ```.dxf```.
|
The composite part files have the same name as the scad file that generates them, with the suffix changed to `.stl` or `.dxf`.
|
||||||
|
|
||||||
The generated files are placed in ```stls/printed``` and ```dxfs/routed```.
|
The generated files are placed in `stls/printed` and `dxfs/routed`.
|
||||||
Any parts that are not covered by the platters / panels are copied into the ```printed``` / ```routed``` directories, so that they contain everything to be made.
|
Any parts that are not covered by the platters / panels are copied into the `printed` / `routed` directories, so that they contain everything to be made.
|
||||||
|
|
||||||
### Multiple configurations
|
### 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
|
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
|
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```.
|
`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 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.
|
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>```.
|
Additionally all the generated file directories (assemblies, bom, stls, dxfs, etc.) are placed in a sub-directory called `<target_name>`.
|
||||||
|
|
||||||
### Other libraries
|
### 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
|
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.
|
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.
|
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.
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
// The assembly is ```include```d so the panel definitions can be overridden to add holes and components.
|
// 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
|
// 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);
|
// parameters to make the assembly views. E.g. module box_assembly() _box_assembly(box);
|
||||||
//
|
//
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
//! A box made from CNC cut panels butted together using printed fixing blocks. Useful for making large
|
//! 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.
|
//! 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
|
//! Needs to be `include`d rather than `use`d to allow the panel definitions to be overridden to add holes
|
||||||
//! and mounted components.
|
//! and mounted components.
|
||||||
//!
|
//!
|
||||||
//! A list specifies the internal dimensions, screw type, top, bottom and side sheet types and the block
|
//! A list specifies the internal dimensions, screw type, top, bottom and side sheet types and the block
|
||||||
|
|
|
@ -25,10 +25,10 @@
|
||||||
//!
|
//!
|
||||||
//! Note that the block with its inserts is defined as a sub assembly, but its fasteners get added to the parent assembly.
|
//! Note that the block with its inserts is defined as a sub assembly, but its fasteners get added to the parent assembly.
|
||||||
//!
|
//!
|
||||||
//! Specific fasteners can be omitted by setting a side's thickness to 0 and the block omitted by setting ```show_block``` to false.
|
//! Specific fasteners can be omitted by setting a side's thickness to 0 and the block omitted by setting `show_block` to false.
|
||||||
//! This allows the block and one set of fasteners to be on one assembly and the other fasteners on the mating assemblies.
|
//! This allows the block and one set of fasteners to be on one assembly and the other fasteners on the mating assemblies.
|
||||||
//!
|
//!
|
||||||
//! Star washers can be omitted by setting ```star_washers``` to false.
|
//! Star washers can be omitted by setting `star_washers` to false.
|
||||||
//
|
//
|
||||||
include <../core.scad>
|
include <../core.scad>
|
||||||
use <../vitamins/insert.scad>
|
use <../vitamins/insert.scad>
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
//! The ends can have screw lugs with four screw positions to choose from, specified by a list of two arrays of four bools.
|
//! The ends can have screw lugs with four screw positions to choose from, specified by a list of two arrays of four bools.
|
||||||
//! If none are enabled then a child object is expected to customise the end and this gets unioned with the blank end.
|
//! If none are enabled then a child object is expected to customise the end and this gets unioned with the blank end.
|
||||||
//! If both ends are customised then two children are expected.
|
//! If both ends are customised then two children are expected.
|
||||||
//! Each child is called twice, once with ```$fasteners``` set to 0 to augment the STL and again with ```$fasteners``` set to 1 to add
|
//! Each child is called twice, once with `$fasteners` set to 0 to augment the STL and again with `$fasteners` set to 1 to add
|
||||||
//! to the assembly, for example to add inserts.
|
//! to the assembly, for example to add inserts.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
// If not, see <https://www.gnu.org/licenses/>.
|
// If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
//
|
//
|
||||||
//! Pintable fan finger guard to match the specified fan. To be ```include```d, not ```use```d.
|
//! 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.
|
//! The ring spacing as well as the number of spokes can be specified, if zero a gasket is generated instead of a guard.
|
||||||
//
|
//
|
||||||
|
|
|
@ -25,10 +25,10 @@
|
||||||
//!
|
//!
|
||||||
//! Note that the block with its inserts is defined as a sub assembly, but its fasteners get added to the parent assembly.
|
//! Note that the block with its inserts is defined as a sub assembly, but its fasteners get added to the parent assembly.
|
||||||
//!
|
//!
|
||||||
//! Specific fasteners can be omitted by setting a side's thickness to 0 and the block omitted by setting ```show_block``` to false.
|
//! Specific fasteners can be omitted by setting a side's thickness to 0 and the block omitted by setting `show_block` to false.
|
||||||
//! This allows the block and one set of fasteners to be on one assembly and the other fasteners on the mating assemblies.
|
//! This allows the block and one set of fasteners to be on one assembly and the other fasteners on the mating assemblies.
|
||||||
//!
|
//!
|
||||||
//! Star washers can be omitted by setting ```star_washers``` to false.
|
//! Star washers can be omitted by setting `star_washers` to false.
|
||||||
//
|
//
|
||||||
include <../core.scad>
|
include <../core.scad>
|
||||||
use <../vitamins/insert.scad>
|
use <../vitamins/insert.scad>
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
//!
|
//!
|
||||||
//! Opening the test in OpenSCAD with its customiser enabled allows these parameters to be played with.
|
//! Opening the test in OpenSCAD with its customiser enabled allows these parameters to be played with.
|
||||||
//!
|
//!
|
||||||
//! Note setting ```thickness1``` or ```thickness2``` to zero in the ```hinge_fastened_assembly()``` removes the screws from one side or the other and
|
//! Note setting `thickness1` or `thickness2` to zero in the `hinge_fastened_assembly()` removes the screws from one side or the other and
|
||||||
//! setting ```show_hinge``` to false removes the hinge.
|
//! setting `show_hinge` to false removes the hinge.
|
||||||
//! This allows the hinges and one set of screws to belong to one assembly and the other set of screws to another assembly.
|
//! This allows the hinges and one set of screws to belong to one assembly and the other set of screws to another assembly.
|
||||||
//
|
//
|
||||||
include <../core.scad>
|
include <../core.scad>
|
||||||
|
|
|
@ -36,7 +36,7 @@ def doc_scripts():
|
||||||
print(
|
print(
|
||||||
'''
|
'''
|
||||||
# Python scripts
|
# Python scripts
|
||||||
These are located in the ```scripts``` subdirectory, which needs to be added to the program search path.
|
These are located in the `scripts` subdirectory, which needs to be added to the program search path.
|
||||||
|
|
||||||
They should work with both Python 2 and Python 3.
|
They should work with both Python 2 and Python 3.
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ They should work with both Python 2 and Python 3.
|
||||||
break
|
break
|
||||||
if not blurb:
|
if not blurb:
|
||||||
print("Missing description for", file)
|
print("Missing description for", file)
|
||||||
print("| ```%s``` | %s |" % (file, blurb), file = doc_file)
|
print("| `%s` | %s |" % (file, blurb), file = doc_file)
|
||||||
|
|
||||||
with open(dir + "/readme.html", "wt") as html_file:
|
with open(dir + "/readme.html", "wt") as html_file:
|
||||||
do_cmd(("python -m markdown -x tables " + doc_name).split(), html_file)
|
do_cmd(("python -m markdown -x tables " + doc_name).split(), html_file)
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
# You should have received a copy of the GNU General Public License along with NopSCADlib.
|
# You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||||
# If not, see <https://www.gnu.org/licenses/>.
|
# If not, see <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
#! Generates all the files for a project by running ```bom.py```, ```stls.py```, ```dxfs.py```, ```render.py``` and ```views.py```.
|
#! Generates all the files for a project by running `bom.py`, `stls.py`, `dxfs.py`, `render.py` and `views.py`.
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
# You should have received a copy of the GNU General Public License along with NopSCADlib.
|
# You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||||
# If not, see <https://www.gnu.org/licenses/>.
|
# If not, see <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
#! Panelises DXF files so they can be routed together by running scad files found in the ```panels``` directory.
|
#! Panelises DXF files so they can be routed together by running scad files found in the `panels` directory.
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import sys
|
import sys
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
# You should have received a copy of the GNU General Public License along with NopSCADlib.
|
# You should have received a copy of the GNU General Public License along with NopSCADlib.
|
||||||
# If not, see <https://www.gnu.org/licenses/>.
|
# If not, see <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
#! Generates build plates of STL files for efficient printing by running scad files found in the ```platters``` directory.
|
#! Generates build plates of STL files for efficient printing by running scad files found in the `platters` directory.
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import sys
|
import sys
|
||||||
|
|
|
@ -1,22 +1,24 @@
|
||||||
|
|
||||||
# Python scripts
|
# Python scripts
|
||||||
These are located in the ```scripts``` subdirectory, which needs to be added to the program search path.
|
These are located in the `scripts` subdirectory, which needs to be added to the program search path.
|
||||||
|
|
||||||
They should work with both Python 2 and Python 3.
|
They should work with both Python 2 and Python 3.
|
||||||
|
|
||||||
| Script | Function |
|
| Script | Function |
|
||||||
|:---|:---|
|
|:---|:---|
|
||||||
| ```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. |
|
||||||
| ```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. |
|
| `dxf.py` | |
|
||||||
| ```gallery.py``` | Finds projects and adds them to the gallery. |
|
| `dxf2pdf.py` | |
|
||||||
| ```make_all.py``` | Generates all the files for a project by running ```bom.py```, ```stls.py```, ```dxfs.py```, ```render.py``` and ```views.py```. |
|
| `dxfs.py` | Generates DXF files for all the routed parts listed on the BOM or a specified list. |
|
||||||
| ```panels.py``` | Panelises DXF files so they can be routed together by running scad files found in the ```panels``` directory. |
|
| `gallery.py` | Finds projects and adds them to the gallery. |
|
||||||
| ```platters.py``` | Generates build plates of STL files for efficient printing by running scad files found in the ```platters``` directory. |
|
| `make_all.py` | Generates all the files for a project by running `bom.py`, `stls.py`, `dxfs.py`, `render.py` and `views.py`. |
|
||||||
| ```render.py``` | Renders STL and DXF files to PNG for inclusion in the build instructions. |
|
| `panels.py` | Panelises DXF files so they can be routed together by running scad files found in the `panels` directory. |
|
||||||
| ```set_config.py``` | Sets the target configuration for multi-target projects that have variable configurations. |
|
| `platters.py` | Generates build plates of STL files for efficient printing by running scad files found in the `platters` directory. |
|
||||||
| ```stls.py``` | Generates STL files for all the printed parts listed on the BOM or a specified list. |
|
| `render.py` | Renders STL and DXF files to PNG for inclusion in the build instructions. |
|
||||||
| ```svgs.py``` | Generates SVG files for all the routed parts listed on the BOM or a specified list. |
|
| `set_config.py` | Sets the target configuration for multi-target projects that have variable configurations. |
|
||||||
| ```tests.py``` | Runs all the tests in the tests directory and makes the readme file with a catalog of the results. |
|
| `stls.py` | Generates STL files for all the printed parts listed on the BOM or a specified list. |
|
||||||
| ```views.py``` | Generates exploded and unexploded assembly views and scrapes build instructions to make readme.md, readme.html and printme.html files for the project. |
|
| `svgs.py` | Generates SVG files for all the routed parts listed on the BOM or a specified list. |
|
||||||
|
| `tests.py` | Runs all the tests in the tests directory and makes the readme file with a catalog of the results. |
|
||||||
|
| `views.py` | Generates exploded and unexploded assembly views and scrapes build instructions to make readme.md, readme.html and printme.html files for the project. |
|
||||||
|
|
|
@ -219,7 +219,7 @@ def tests(tests):
|
||||||
if things:
|
if things:
|
||||||
body += ['### %s\n| %s | Description |\n|:--- |:--- |' % (thing.title(), heading)]
|
body += ['### %s\n| %s | Description |\n|:--- |:--- |' % (thing.title(), heading)]
|
||||||
for item in sorted(things):
|
for item in sorted(things):
|
||||||
body += ['| ```%s``` | %s |' % (item, things[item])]
|
body += ['| `%s` | %s |' % (item, things[item])]
|
||||||
body += ['']
|
body += ['']
|
||||||
|
|
||||||
body += ["![%s](%s)\n" %(base_name, png_name)]
|
body += ["![%s](%s)\n" %(base_name, png_name)]
|
||||||
|
@ -252,7 +252,7 @@ def tests(tests):
|
||||||
desc = ''
|
desc = ''
|
||||||
if thing == "vitamins":
|
if thing == "vitamins":
|
||||||
vit = item.split(':')
|
vit = item.split(':')
|
||||||
name = '```' + vit[0] + '```' if vit[0] else ''
|
name = '`' + vit[0] + '`' if vit[0] else ''
|
||||||
while '[[' in name and ']]' in name:
|
while '[[' in name and ']]' in name:
|
||||||
i = name.find('[[')
|
i = name.find('[[')
|
||||||
j = name.find(']]') + 2
|
j = name.find(']]') + 2
|
||||||
|
|
|
@ -22,14 +22,14 @@
|
||||||
//
|
//
|
||||||
include <../global_defs.scad>
|
include <../global_defs.scad>
|
||||||
|
|
||||||
function bezier(t, v) = //! Returns a point at distance ```t``` [0 - 1] along the curve with control points ```v```
|
function bezier(t, v) = //! Returns a point at distance `t` [0 - 1] along the curve with control points `v`
|
||||||
(len(v) > 2) ? bezier(t, [for (i = [0 : len(v) - 2]) v[i] * (1 - t) + v[i + 1] * (t)])
|
(len(v) > 2) ? bezier(t, [for (i = [0 : len(v) - 2]) v[i] * (1 - t) + v[i + 1] * (t)])
|
||||||
: v[0] * (1 - t) + v[1] * (t);
|
: v[0] * (1 - t) + v[1] * (t);
|
||||||
|
|
||||||
function bezier_path(v, steps = 100) = //! Returns a Bezier path from control points ```v``` with ```steps``` segments
|
function bezier_path(v, steps = 100) = //! Returns a Bezier path from control points `v` with `steps` segments
|
||||||
[for(i = [0 : steps], t = i / steps) bezier(t, v)];
|
[for(i = [0 : steps], t = i / steps) bezier(t, v)];
|
||||||
|
|
||||||
function bezier_length(v, delta = 0.01, t = 0, length = 0) = //! Calculate the length of a Bezier curve from control points ```v```
|
function bezier_length(v, delta = 0.01, t = 0, length = 0) = //! Calculate the length of a Bezier curve from control points `v`
|
||||||
t > 1 ? length
|
t > 1 ? length
|
||||||
: bezier_length(v, delta, t + delta, length + norm(bezier(t, v) - bezier(t + delta, v)));
|
: bezier_length(v, delta, t + delta, length + norm(bezier(t, v) - bezier(t + delta, v)));
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ function adjust_bezier(v, r) =
|
||||||
let(extension = (v[1] - v[0]) * (r - 1))
|
let(extension = (v[1] - v[0]) * (r - 1))
|
||||||
[v[0], v[1] + extension, v[2] + extension, v[3]];
|
[v[0], v[1] + extension, v[2] + extension, v[3]];
|
||||||
|
|
||||||
function adjust_bezier_length(v, l, eps = 0.001, r1 = 1.0, r2 = 1.5, l1, l2) = //! Adjust Bezier control points ```v``` to get the required curve length ```l```
|
function adjust_bezier_length(v, l, eps = 0.001, r1 = 1.0, r2 = 1.5, l1, l2) = //! Adjust Bezier control points `v` to get the required curve length `l`
|
||||||
let(l1 = l1 != undef ? l1 : bezier_length(adjust_bezier(v, r1)),
|
let(l1 = l1 != undef ? l1 : bezier_length(adjust_bezier(v, r1)),
|
||||||
l2 = l2 != undef ? l2 : bezier_length(adjust_bezier(v, r2))
|
l2 = l2 != undef ? l2 : bezier_length(adjust_bezier(v, r2))
|
||||||
) abs(l1 - l) < eps ? adjust_bezier(v, r1)
|
) abs(l1 - l) < eps ? adjust_bezier(v, r1)
|
||||||
|
@ -45,10 +45,10 @@ function adjust_bezier_length(v, l, eps = 0.001, r1 = 1.0, r2 = 1.5, l1, l2) = /
|
||||||
abs(r - r1) < abs(r - r2) ? adjust_bezier_length(v, l, eps, r, r1, undef, l1)
|
abs(r - r1) < abs(r - r2) ? adjust_bezier_length(v, l, eps, r, r1, undef, l1)
|
||||||
: adjust_bezier_length(v, l, eps, r, r2, undef, l2);
|
: adjust_bezier_length(v, l, eps, r, r2, undef, l2);
|
||||||
|
|
||||||
function bezier_min_z(v, steps = 100, z = inf, i = 0) = //! Calculate the minimum z coordinate of a Bezier curve from control points ```v```
|
function bezier_min_z(v, steps = 100, z = inf, i = 0) = //! Calculate the minimum z coordinate of a Bezier curve from control points `v`
|
||||||
i <= steps ? bezier_min_z(v, steps, min(z, bezier(i / steps, v).z), i + 1) : z;
|
i <= steps ? bezier_min_z(v, steps, min(z, bezier(i / steps, v).z), i + 1) : z;
|
||||||
|
|
||||||
function adjust_bezier_z(v, z, eps = 0.001, r1 = 1, r2 = 1.5, z1, z2) = //! Adjust Bezier control points ```v``` to get the required minimum ```z```
|
function adjust_bezier_z(v, z, eps = 0.001, r1 = 1, r2 = 1.5, z1, z2) = //! Adjust Bezier control points `v` to get the required minimum `z`
|
||||||
let(z1 = z1 != undef ? z1 : bezier_min_z(adjust_bezier(v, r1)),
|
let(z1 = z1 != undef ? z1 : bezier_min_z(adjust_bezier(v, r1)),
|
||||||
z2 = z2 != undef ? z2 : bezier_min_z(adjust_bezier(v, r2))
|
z2 = z2 != undef ? z2 : bezier_min_z(adjust_bezier(v, r2))
|
||||||
) abs(z1 - z) < eps ? adjust_bezier(v, r1)
|
) abs(z1 - z) < eps ? adjust_bezier(v, r1)
|
||||||
|
|
|
@ -20,25 +20,25 @@
|
||||||
//
|
//
|
||||||
//! Catenary curve to model hanging wires, etc.
|
//! Catenary curve to model hanging wires, etc.
|
||||||
//!
|
//!
|
||||||
//! Although the equation of the curve is simply ```y = a cosh(x / a)``` there is no explicit formula to calculate the constant ```a``` or the range of ```x``` given the
|
//! Although the equation of the curve is simply `y = a cosh(x / a)` there is no explicit formula to calculate the constant `a` or the range of `x` given the
|
||||||
//! length of the cable and the end point coordinates. See <https://en.wikipedia.org/wiki/Catenary#Determining_parameters>. The Newton-Raphson method is used to find
|
//! length of the cable and the end point coordinates. See <https://en.wikipedia.org/wiki/Catenary#Determining_parameters>. The Newton-Raphson method is used to find
|
||||||
//! ```a``` numerically, see <https://en.wikipedia.org/wiki/Newton%27s_method>.
|
//! `a` numerically, see <https://en.wikipedia.org/wiki/Newton%27s_method>.
|
||||||
//!
|
//!
|
||||||
//! The coordinates of the lowest point on the curve can be retrieved by calling ```catenary_points()``` with ```steps``` equal to zero.
|
//! The coordinates of the lowest point on the curve can be retrieved by calling `catenary_points()` with `steps` equal to zero.
|
||||||
//
|
//
|
||||||
include <core/core.scad>
|
include <core/core.scad>
|
||||||
use <maths.scad>
|
use <maths.scad>
|
||||||
|
|
||||||
function catenary(t, a) = let(u = argsinh(t)) a * [u, cosh(u)]; //! Parametric catenary function linear along the length of the curve.
|
function catenary(t, a) = let(u = argsinh(t)) a * [u, cosh(u)]; //! Parametric catenary function linear along the length of the curve.
|
||||||
function catenary_s(d, a) = 2 * a * sinh(d / a); //! Length of a symmetric catenary with width ```2d```.
|
function catenary_s(d, a) = 2 * a * sinh(d / a); //! Length of a symmetric catenary with width `2d`.
|
||||||
function catenary_ds_by_da(d, a) = 2 * sinh(d / a) - 2 * d / a * cosh(d / a); //! First derivative of the length with respect to ```a```.
|
function catenary_ds_by_da(d, a) = 2 * sinh(d / a) - 2 * d / a * cosh(d / a); //! First derivative of the length with respect to `a`.
|
||||||
|
|
||||||
function catenary_find_a(d, l, a = 1, best_e = inf, best_a = 1) = //! Find the catenary constant ```a```, given half the horizontal span and the length.
|
function catenary_find_a(d, l, a = 1, best_e = inf, best_a = 1) = //! Find the catenary constant `a`, given half the horizontal span and the length.
|
||||||
assert(l > 2 * d, "Not long enough to span the gap") assert(d) let(error = abs(catenary_s(d, a) - l))
|
assert(l > 2 * d, "Not long enough to span the gap") assert(d) let(error = abs(catenary_s(d, a) - l))
|
||||||
error >= best_e && error < 0.0001 ? best_a
|
error >= best_e && error < 0.0001 ? best_a
|
||||||
: catenary_find_a(d, l, max(a - (catenary_s(d, a) - l) / catenary_ds_by_da(d, a), d / argsinh(1e99)), error, a);
|
: catenary_find_a(d, l, max(a - (catenary_s(d, a) - l) / catenary_ds_by_da(d, a), d / argsinh(1e99)), error, a);
|
||||||
|
|
||||||
function catenary_points(l, x, y, steps = 100) = //! Returns a list of 2D points on the curve that goes from the origin to ```(x,y)``` and has length ```l```.
|
function catenary_points(l, x, y, steps = 100) = //! Returns a list of 2D points on the curve that goes from the origin to `(x,y)` and has length `l`.
|
||||||
let(
|
let(
|
||||||
d = x / 2,
|
d = x / 2,
|
||||||
a = catenary_find_a(d, sqrt(sqr(l) - sqr(y))), // Find a to get the correct length
|
a = catenary_find_a(d, sqrt(sqr(l) - sqr(y))), // Find a to get the correct length
|
||||||
|
|
|
@ -18,24 +18,24 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
//
|
//
|
||||||
//! Bill Of Materials generation via echo and the ```bom.py``` script. Also handles exploded assembly views and posing.
|
//! Bill Of Materials generation via echo and the `bom.py` script. Also handles exploded assembly views and posing.
|
||||||
//! Assembly instructions can precede the module definition that makes the assembly.
|
//! Assembly instructions can precede the module definition that makes the assembly.
|
||||||
//!
|
//!
|
||||||
//! Assembly views shown in the instructions can be large or small and this is deduced by looking at the size of the printed parts involved and if any routed
|
//! Assembly views shown in the instructions can be large or small and this is deduced by looking at the size of the printed parts involved and if any routed
|
||||||
//! parts are used.
|
//! parts are used.
|
||||||
//! This heuristic isn't always correct, so the default can be overridden by setting the ```big``` parameter of ```assembly``` to ```true``` or ```false```.
|
//! This heuristic isn't always correct, so the default can be overridden by setting the `big` parameter of `assembly` to `true` or `false`.
|
||||||
//!
|
//!
|
||||||
//! The example below shows how to define a vitamin and incorporate it into an assembly with sub-assemblies and make an exploded view.
|
//! 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 heirachical BOMs are also generated for real projects.
|
//! The resulting flat BOM is shown but heirachical BOMs are also generated for real projects.
|
||||||
//
|
//
|
||||||
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 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];
|
||||||
if($exploded && is_undef($exploded_parent) && norm(v)) {
|
if($exploded && is_undef($exploded_parent) && norm(v)) {
|
||||||
|
@ -55,7 +55,7 @@ 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 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.
|
||||||
if(is_undef($pose) || !is_undef($posed) || (!is_undef(exploded) && exploded != !!exploded()))
|
if(is_undef($pose) || !is_undef($posed) || (!is_undef(exploded) && exploded != !!exploded()))
|
||||||
children();
|
children();
|
||||||
else
|
else
|
||||||
|
@ -67,7 +67,7 @@ module pose(a = [55, 0, 25], t = [0, 0, 0], exploded = undef) //! Pose an
|
||||||
translate(-t)
|
translate(-t)
|
||||||
children();
|
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()))
|
||||||
children();
|
children();
|
||||||
else
|
else
|
||||||
|
@ -75,7 +75,7 @@ module pose_hflip(exploded = undef) //! Pose an STL or assembly for render
|
||||||
hflip()
|
hflip()
|
||||||
children();
|
children();
|
||||||
|
|
||||||
module 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.
|
module 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.
|
||||||
if(is_undef($pose) || !is_undef($posed) || (!is_undef(exploded) && exploded != !!exploded()))
|
if(is_undef($pose) || !is_undef($posed) || (!is_undef(exploded) && exploded != !!exploded()))
|
||||||
children();
|
children();
|
||||||
else
|
else
|
||||||
|
@ -84,7 +84,7 @@ module pose_vflip(exploded = undef) //! Pose an STL or assembly for render
|
||||||
children();
|
children();
|
||||||
|
|
||||||
|
|
||||||
module assembly(name, big = undef) { //! 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) { //! 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) ? "" : str("(big=", big, ")");
|
args = is_undef(big) ? "" : str("(big=", big, ")");
|
||||||
echo(str("~", name, "_assembly", args, "{"));
|
echo(str("~", name, "_assembly", args, "{"));
|
||||||
|
@ -101,20 +101,20 @@ module assembly(name, big = undef) { //! Name an assembly that will appear on
|
||||||
echo(str("~}", name, "_assembly"));
|
echo(str("~}", name, "_assembly"));
|
||||||
}
|
}
|
||||||
|
|
||||||
module 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.
|
module 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.
|
||||||
$stl_colour = colour;
|
$stl_colour = colour;
|
||||||
color(colour, alpha)
|
color(colour, alpha)
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
|
|
||||||
module stl(name) { //! Name an stl that will appear on the BOM, there needs to a module named ```<name>_stl``` to make it
|
module stl(name) { //! Name an stl that will appear on the BOM, there needs to a module named `<name>_stl` to make it
|
||||||
if(bom_mode()) {
|
if(bom_mode()) {
|
||||||
colour = is_undef($stl_colour) ? pp1_colour : $stl_colour;
|
colour = is_undef($stl_colour) ? pp1_colour : $stl_colour;
|
||||||
echo(str("~", name, ".stl(colour='", colour, "')"));
|
echo(str("~", name, ".stl(colour='", colour, "')"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module dxf(name) { //! Name a dxf that will appear on the BOM, there needs to a module named ```<name>_dxf``` to make it
|
module dxf(name) { //! Name a dxf that will appear on the BOM, there needs to a module named `<name>_dxf` to make it
|
||||||
if(bom_mode()) {
|
if(bom_mode()) {
|
||||||
if(is_undef($dxf_colour))
|
if(is_undef($dxf_colour))
|
||||||
echo(str("~", name, ".dxf"));
|
echo(str("~", name, ".dxf"));
|
||||||
|
@ -123,9 +123,9 @@ module dxf(name) { //! Name a dxf that will appear on the B
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 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()```
|
function arg(value, default, name = "") = //! Create string for arg if not default, helper for `vitamin()`
|
||||||
value == default ? ""
|
value == default ? ""
|
||||||
: name ? str(", ", name, " = ", value_string(value))
|
: name ? str(", ", name, " = ", value_string(value))
|
||||||
: str(", ", value_string(value));
|
: str(", ", value_string(value));
|
||||||
|
|
|
@ -29,11 +29,11 @@ function mm(x) = x;
|
||||||
function cm(x) = x * 10.0; //! cm to mm conversion
|
function cm(x) = x * 10.0; //! cm to mm conversion
|
||||||
function m(x) = x * 1000.0; //! m to mm conversion
|
function m(x) = x * 1000.0; //! m to mm conversion
|
||||||
|
|
||||||
function sqr(x) = x * x; //! Returns the square of ```x```
|
function sqr(x) = x * x; //! Returns the square of `x`
|
||||||
function echoit(x) = echo(x) x; //! Echo expression and return it, useful for debugging
|
function echoit(x) = echo(x) x; //! Echo expression and return it, useful for debugging
|
||||||
function no_point(str) = chr([for(c = str(str)) if(c == ".") ord("p") else ord(c)]);//! Replace decimal point in string with 'p'
|
function no_point(str) = chr([for(c = str(str)) if(c == ".") ord("p") else ord(c)]);//! Replace decimal point in string with 'p'
|
||||||
function in(list, x) = !!len([for(v = list) if(v == x) true]); //! Returns true if ```x``` is an element in the ```list```
|
function in(list, x) = !!len([for(v = list) if(v == x) true]); //! Returns true if `x` is an element in the `list`
|
||||||
function Len(x) = is_list(x) ? len(x) : 0; //! Returns the length of a list or 0 if ```x``` is not a list
|
function Len(x) = is_list(x) ? len(x) : 0; //! Returns the length of a list or 0 if `x` is not a list
|
||||||
function r2sides(r) = $fn ? $fn : ceil(max(min(360/ $fa, r * 2 * PI / $fs), 5)); //! Replicates the OpenSCAD logic to calculate the number of sides from the radius
|
function r2sides(r) = $fn ? $fn : ceil(max(min(360/ $fa, r * 2 * PI / $fs), 5)); //! Replicates the OpenSCAD logic to calculate the number of sides from the radius
|
||||||
function r2sides4n(r) = floor((r2sides(r) + 3) / 4) * 4; //! Round up the number of sides to a multiple of 4 to ensure points land on all axes
|
function r2sides4n(r) = floor((r2sides(r) + 3) / 4) * 4; //! Round up the number of sides to a multiple of 4 to ensure points land on all axes
|
||||||
function limit(x, min, max) = max(min(x, max), min); //! Force x in range min <= x <= max
|
function limit(x, min, max) = max(min(x, max), min); //! Force x in range min <= x <= max
|
||||||
|
@ -52,14 +52,14 @@ function slice(list, start = 0, end = undef) = let( //! Slice a list or string w
|
||||||
) is_string(list) ? slice_str(list, start, end) : [for(i = [start : 1 : end - 1]) list[i]];
|
) is_string(list) ? slice_str(list, start, end) : [for(i = [start : 1 : end - 1]) list[i]];
|
||||||
|
|
||||||
|
|
||||||
module render_if(render = true, convexity = 2) //! Renders an object if ```render``` is true, otherwise leaves it unrendered
|
module render_if(render = true, convexity = 2) //! Renders an object if `render` is true, otherwise leaves it unrendered
|
||||||
if (render)
|
if (render)
|
||||||
render(convexity = convexity)
|
render(convexity = convexity)
|
||||||
children();
|
children();
|
||||||
else
|
else
|
||||||
children();
|
children();
|
||||||
|
|
||||||
module extrude_if(h, center = true) //! Extrudes 2D object to 3D when ```h``` is nonzero, otherwise leaves it 2D
|
module extrude_if(h, center = true) //! Extrudes 2D object to 3D when `h` is nonzero, otherwise leaves it 2D
|
||||||
if(h)
|
if(h)
|
||||||
linear_extrude(h, center = center, convexity = 2) // 3D
|
linear_extrude(h, center = center, convexity = 2) // 3D
|
||||||
children();
|
children();
|
||||||
|
@ -81,7 +81,7 @@ module semi_circle(r, d = undef) //! A semi circle in the pos
|
||||||
square([2 * sq, sq]);
|
square([2 * sq, sq]);
|
||||||
}
|
}
|
||||||
|
|
||||||
module right_triangle(width, height, h, center = true) //! A right angled triangle with the 90° corner at the origin. 3D when ```h``` is nonzero, otherwise 2D
|
module right_triangle(width, height, h, center = true) //! A right angled triangle with the 90° corner at the origin. 3D when `h` is nonzero, otherwise 2D
|
||||||
extrude_if(h, center = center)
|
extrude_if(h, center = center)
|
||||||
polygon(points = [[0,0], [width, 0], [0, height]]);
|
polygon(points = [[0,0], [width, 0], [0, height]]);
|
||||||
|
|
||||||
|
|
|
@ -20,29 +20,28 @@
|
||||||
//
|
//
|
||||||
//! Rectangle with rounded corners.
|
//! Rectangle with rounded corners.
|
||||||
//
|
//
|
||||||
module rounded_square(size, r, center = true) //! Like ```square()``` but with with rounded corners
|
module rounded_square(size, r, center = true) //! Like `square()` but with with rounded corners
|
||||||
{
|
{
|
||||||
$fn = r2sides4n(r);
|
$fn = r2sides4n(r);
|
||||||
offset(r) offset(-r) square(size, center = center);
|
offset(r) offset(-r) square(size, center = center);
|
||||||
}
|
}
|
||||||
|
|
||||||
module rounded_rectangle(size, r, center = true, xy_center = true) //! Like ```cube()``` but corners rounded in XY plane and separate centre options for xy and z.
|
module rounded_rectangle(size, r, center = true, xy_center = true) //! Like `cube()` but corners rounded in XY plane and separate centre options for xy and z.
|
||||||
{
|
{
|
||||||
linear_extrude(size.z, center = center)
|
linear_extrude(size.z, center = center)
|
||||||
rounded_square([size.x, size.y], r, xy_center);
|
rounded_square([size.x, size.y], r, xy_center);
|
||||||
}
|
}
|
||||||
|
|
||||||
module rounded_rectangle_xz(size, r, center = true, xy_center = true) //! Like ```cube()``` but corners rounded in XZ plane and separate centre options for xy and z.
|
module rounded_rectangle_xz(size, r, center = true, xy_center = true) //! Like `cube()` but corners rounded in XZ plane and separate centre options for xy and z.
|
||||||
{
|
{
|
||||||
translate([xy_center ? 0 : size.x / 2, xy_center ? 0 : size.y / 2, center ? 0 : size.z / 2])
|
translate([xy_center ? 0 : size.x / 2, xy_center ? 0 : size.y / 2, center ? 0 : size.z / 2])
|
||||||
rotate([90, 0, 0])
|
rotate([90, 0, 0])
|
||||||
rounded_rectangle([size.x, size.z, size.y], r, center = true, xy_center = true);
|
rounded_rectangle([size.x, size.z, size.y], r, center = true, xy_center = true);
|
||||||
}
|
}
|
||||||
|
|
||||||
module rounded_rectangle_yz(size, r, center = true, xy_center = true) //! Like ```cube()``` but corners rounded in YX plane and separate centre options for xy and z.
|
module rounded_rectangle_yz(size, r, center = true, xy_center = true) //! Like `cube()` but corners rounded in YX plane and separate centre options for xy and z.
|
||||||
{
|
{
|
||||||
translate([xy_center ? 0 : size.x / 2, xy_center ? 0 : size.y / 2, center ? 0 : size.z / 2])
|
translate([xy_center ? 0 : size.x / 2, xy_center ? 0 : size.y / 2, center ? 0 : size.z / 2])
|
||||||
rotate([90, 0, 90])
|
rotate([90, 0, 90])
|
||||||
rounded_rectangle([size.y, size.z, size.x], r, center = true, xy_center = true);
|
rounded_rectangle([size.y, size.z, size.x], r, center = true, xy_center = true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
//! Redefines `sphere()` to always have a vertex on all six half axes I.e. vertices at the poles and the equator and `$fn` a multiple of four.
|
//! Redefines `sphere()` to always have a vertex on all six half axes I.e. vertices at the poles and the equator and `$fn` a multiple of four.
|
||||||
//! This ensures `hull` and `minkowski` results have the correct dimensions when spheres are placed at the corners.
|
//! This ensures `hull` and `minkowski` results have the correct dimensions when spheres are placed at the corners.
|
||||||
|
|
||||||
module sphere(r = 1, d = undef) { //! Override ```sphere``` so that has vertices on all three axes. Has the advantage of giving correct dimensions when hulled
|
module sphere(r = 1, d = undef) { //! Override `sphere` so that has vertices on all three axes. Has the advantage of giving correct dimensions when hulled
|
||||||
R = is_undef(d) ? r : d / 2;
|
R = is_undef(d) ? r : d / 2;
|
||||||
rotate_extrude($fn = r2sides4n(R))
|
rotate_extrude($fn = r2sides4n(R))
|
||||||
rotate(-90)
|
rotate(-90)
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
//! Using teardrop_plus() or setting the plus option on other modules will elongate the teardrop vertically by the layer height, so when sliced the staircase tips
|
//! Using teardrop_plus() or setting the plus option on other modules will elongate the teardrop vertically by the layer height, so when sliced the staircase tips
|
||||||
//! do not intrude into the circle. See <https://hydraraptor.blogspot.com/2020/07/horiholes-2.html>
|
//! do not intrude into the circle. See <https://hydraraptor.blogspot.com/2020/07/horiholes-2.html>
|
||||||
//
|
//
|
||||||
module teardrop(h, r, center = true, truncate = true, chamfer = 0, plus = false) { //! For making horizontal holes that don't need support material, set ```truncate = false``` to make traditional RepRap teardrops that don't even need bridging
|
module teardrop(h, r, center = true, truncate = true, chamfer = 0, plus = false) { //! For making horizontal holes that don't need support material, set `truncate = false` to make traditional RepRap teardrops that don't even need bridging
|
||||||
module teardrop_2d(r, truncate) {
|
module teardrop_2d(r, truncate) {
|
||||||
er = layer_height / 2 - eps; // Extrustion edge radius
|
er = layer_height / 2 - eps; // Extrustion edge radius
|
||||||
R = plus ? r + er : r; // Corrected radius
|
R = plus ? r + er : r; // Corrected radius
|
||||||
|
|
|
@ -24,17 +24,17 @@
|
||||||
//! <https://khkgears.net/new/gear_knowledge/gear_technical_reference/calculation_gear_dimensions.html>
|
//! <https://khkgears.net/new/gear_knowledge/gear_technical_reference/calculation_gear_dimensions.html>
|
||||||
//! and <https://www.tec-science.com/mechanical-power-transmission/involute-gear/calculation-of-involute-gears/>
|
//! and <https://www.tec-science.com/mechanical-power-transmission/involute-gear/calculation-of-involute-gears/>
|
||||||
//!
|
//!
|
||||||
//! ```involute_gear_profile()``` returns a polygon that can have the bore and spokes, etc, subtracted from it before linear extruding it to 3D.
|
//! `involute_gear_profile()` returns a polygon that can have the bore and spokes, etc, subtracted from it before linear extruding it to 3D.
|
||||||
//! Helical gears can be made using ```twist``` and bevel gears using ```scale``` parameters of ```linear_extrude()```.
|
//! Helical gears can be made using `twist` and bevel gears using `scale` parameters of `linear_extrude()`.
|
||||||
//!
|
//!
|
||||||
//! Gears with less than 19 teeth (when pressure angle is 20) are profile shifted to avoid undercutting the tooth root. 7 teeth is considered
|
//! Gears with less than 19 teeth (when pressure angle is 20) are profile shifted to avoid undercutting the tooth root. 7 teeth is considered
|
||||||
//! the practical minimum.
|
//! the practical minimum.
|
||||||
//!
|
//!
|
||||||
//! The clearance between tip and root defaults to module / 6, but can be overridden by setting the ```clearance``` parameter.
|
//! The clearance between tip and root defaults to module / 6, but can be overridden by setting the `clearance` parameter.
|
||||||
//!
|
//!
|
||||||
//! The origin of the rack is the left end of the pitch line and its width is below the pitch line. I.e. it does not include the addendum.
|
//! The origin of the rack is the left end of the pitch line and its width is below the pitch line. I.e. it does not include the addendum.
|
||||||
//!
|
//!
|
||||||
//! ```involute_worm_profile()``` returns a tooth profile that can be passed to ```thread()``` to make worms.
|
//! `involute_worm_profile()` returns a tooth profile that can be passed to `thread()` to make worms.
|
||||||
//
|
//
|
||||||
include <core/core.scad>
|
include <core/core.scad>
|
||||||
use <maths.scad>
|
use <maths.scad>
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
//
|
//
|
||||||
include <../utils/core/core.scad>
|
include <../utils/core/core.scad>
|
||||||
|
|
||||||
module hanging_hole(z, ir, h = 100, h2 = 100) { //! Hole radius ```ir``` hanging at the specified ```z``` value above a void who's shape is given by a 2D child
|
module hanging_hole(z, ir, h = 100, h2 = 100) { //! Hole radius `ir` hanging at the specified `z` value above a void who's shape is given by a 2D child
|
||||||
module polyhole(r, h, n = 8) {
|
module polyhole(r, h, n = 8) {
|
||||||
if(h > 0)
|
if(h > 0)
|
||||||
rotate(180 / n) {
|
rotate(180 / n) {
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
//
|
//
|
||||||
//! Utilities for depicting the staircase slicing of horizontal holes made with [`teardrop_plus()`](#teardrops), see <https://hydraraptor.blogspot.com/2020/07/horiholes-2.html>
|
//! Utilities for depicting the staircase slicing of horizontal holes made with [`teardrop_plus()`](#teardrops), see <https://hydraraptor.blogspot.com/2020/07/horiholes-2.html>
|
||||||
//!
|
//!
|
||||||
//! ```horicylinder()``` makes cylinders that fit inside a round hole. Layers that are less than 2 filaments wide and layers that need more than a 45 degree overhang are omitted.
|
//! `horicylinder()` makes cylinders that fit inside a round hole. Layers that are less than 2 filaments wide and layers that need more than a 45 degree overhang are omitted.
|
||||||
//
|
//
|
||||||
include <../utils/core/core.scad>
|
include <../utils/core/core.scad>
|
||||||
|
|
||||||
|
|
|
@ -22,11 +22,11 @@
|
||||||
//
|
//
|
||||||
include <../global_defs.scad>
|
include <../global_defs.scad>
|
||||||
|
|
||||||
function layout_offset(widths, i, gap = 2) = //! Calculate the offset for the ```i```th item
|
function layout_offset(widths, i, gap = 2) = //! Calculate the offset for the `i`th item
|
||||||
i == 0 ? widths[0] / 2
|
i == 0 ? widths[0] / 2
|
||||||
: layout_offset(widths, i - 1, gap) + widths[i - 1] / 2 + gap + widths[i] / 2;
|
: layout_offset(widths, i - 1, gap) + widths[i - 1] / 2 + gap + widths[i] / 2;
|
||||||
|
|
||||||
module layout(widths, gap = 2, no_offset = false) //! Layout children passing ```$i```
|
module layout(widths, gap = 2, no_offset = false) //! Layout children passing `$i`
|
||||||
translate([no_offset ? -widths[0] / 2 : 0, 0])
|
translate([no_offset ? -widths[0] / 2 : 0, 0])
|
||||||
for($i = [0 : 1 : len(widths) - 1])
|
for($i = [0 : 1 : len(widths) - 1])
|
||||||
translate([layout_offset(widths, $i, gap), 0])
|
translate([layout_offset(widths, $i, gap), 0])
|
||||||
|
|
|
@ -33,7 +33,7 @@ function argcosh(x) = ln(x + sqrt(sqr(x) - 1)); //! inverse hyperbolic cosine
|
||||||
function argtanh(x) = ln((1 + x) / (1 - x)) / 2;//! inverse hyperbolic tangent
|
function argtanh(x) = ln((1 + x) / (1 - x)) / 2;//! inverse hyperbolic tangent
|
||||||
function argcoth(x) = ln((x + 1) / (x - 1)) / 2;//! inverse hyperbolic cotangent
|
function argcoth(x) = ln((x + 1) / (x - 1)) / 2;//! inverse hyperbolic cotangent
|
||||||
|
|
||||||
function translate(v) = let(u = is_list(v) ? len(v) == 2 ? [v.x, v.y, 0] //! Generate a 4x4 translation matrix, ```v``` can be ```[x, y]```, ```[x, y, z]``` or ```z```
|
function translate(v) = let(u = is_list(v) ? len(v) == 2 ? [v.x, v.y, 0] //! Generate a 4x4 translation matrix, `v` can be `[x, y]`, `[x, y, z]` or `z`
|
||||||
: v
|
: v
|
||||||
: [0, 0, v])
|
: [0, 0, v])
|
||||||
[ [1, 0, 0, u.x],
|
[ [1, 0, 0, u.x],
|
||||||
|
@ -41,7 +41,7 @@ function translate(v) = let(u = is_list(v) ? len(v) == 2 ? [v.x, v.y, 0] //! Gen
|
||||||
[0, 0, 1, u.z],
|
[0, 0, 1, u.z],
|
||||||
[0, 0, 0, 1] ];
|
[0, 0, 0, 1] ];
|
||||||
|
|
||||||
function rotate(a, v) = //! Generate a 4x4 rotation matrix, ```a``` can be a vector of three angles or a single angle around ```z```, or around axis ```v```
|
function rotate(a, v) = //! Generate a 4x4 rotation matrix, `a` can be a vector of three angles or a single angle around `z`, or around axis `v`
|
||||||
is_undef(v) ? let(av = is_list(a) ? a : [0, 0, a],
|
is_undef(v) ? let(av = is_list(a) ? a : [0, 0, a],
|
||||||
cx = cos(av[0]),
|
cx = cos(av[0]),
|
||||||
cy = cos(av[1]),
|
cy = cos(av[1]),
|
||||||
|
@ -80,7 +80,7 @@ function rot2_z(a) = //! Generate a 2x2 matrix to rotate around z
|
||||||
[ [ c, -s],
|
[ [ c, -s],
|
||||||
[ s, c] ];
|
[ s, c] ];
|
||||||
|
|
||||||
function scale(v) = let(s = is_list(v) ? v : [v, v, v]) //! Generate a 4x4 matrix that scales by ```v```, which can be a vector of xyz factors or a scalar to scale all axes equally
|
function scale(v) = let(s = is_list(v) ? v : [v, v, v]) //! Generate a 4x4 matrix that scales by `v`, which can be a vector of xyz factors or a scalar to scale all axes equally
|
||||||
[
|
[
|
||||||
[s.x, 0, 0, 0],
|
[s.x, 0, 0, 0],
|
||||||
[0, s.y, 0, 0],
|
[0, s.y, 0, 0],
|
||||||
|
@ -88,11 +88,11 @@ function scale(v) = let(s = is_list(v) ? v : [v, v, v]) //! Generate a 4x4 matr
|
||||||
[0, 0, 0, 1]
|
[0, 0, 0, 1]
|
||||||
];
|
];
|
||||||
|
|
||||||
function vec3(v) = [v.x, v.y, v.z]; //! Return a 3 vector with the first three elements of ```v```
|
function vec3(v) = [v.x, v.y, v.z]; //! Return a 3 vector with the first three elements of `v`
|
||||||
function vec4(v) = [v.x, v.y, v.z, 1]; //! Return a 4 vector with the first three elements of ```v```
|
function vec4(v) = [v.x, v.y, v.z, 1]; //! Return a 4 vector with the first three elements of `v`
|
||||||
function transform(v, m) = vec3(m * [v.x, v.y, v.z, 1]); //! Apply 4x4 transform to a 3 vector by extending it and cropping it again
|
function transform(v, m) = vec3(m * [v.x, v.y, v.z, 1]); //! Apply 4x4 transform to a 3 vector by extending it and cropping it again
|
||||||
function transform_points(path, m) = [for(p = path) transform(p, m)]; //! Apply transform to a path
|
function transform_points(path, m) = [for(p = path) transform(p, m)]; //! Apply transform to a path
|
||||||
function unit(v) = let(n = norm(v)) n ? v / n : v; //! Convert ```v``` to a unit vector
|
function unit(v) = let(n = norm(v)) n ? v / n : v; //! Convert `v` to a unit vector
|
||||||
|
|
||||||
function transpose(m) = [ for(j = [0 : len(m[0]) - 1]) [ for(i = [0 : len(m) - 1]) m[i][j] ] ]; //! Transpose an arbitrary size matrix
|
function transpose(m) = [ for(j = [0 : len(m[0]) - 1]) [ for(i = [0 : len(m) - 1]) m[i][j] ] ]; //! Transpose an arbitrary size matrix
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
//! If `chamfer_base` is true then the bottom edge is made suitable for 3D printing by chamfering when the angle gets shallower than 45 degrees.
|
//! If `chamfer_base` is true then the bottom edge is made suitable for 3D printing by chamfering when the angle gets shallower than 45 degrees.
|
||||||
include <../utils/core/core.scad>
|
include <../utils/core/core.scad>
|
||||||
|
|
||||||
module offset_3D(r, chamfer_base = false) { //! Offset 3D shape by specified radius ```r```, positive or negative.
|
module offset_3D(r, chamfer_base = false) { //! Offset 3D shape by specified radius `r`, positive or negative.
|
||||||
module ball(r)
|
module ball(r)
|
||||||
if(chamfer_base)
|
if(chamfer_base)
|
||||||
rotate_extrude()
|
rotate_extrude()
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
//
|
//
|
||||||
include <../utils/core/core.scad>
|
include <../utils/core/core.scad>
|
||||||
|
|
||||||
module quadrant(w, r, center = false) { //! Draw a square with one rounded corner, can be centered on the arc centre, when ```center``` is ```true```.
|
module quadrant(w, r, center = false) { //! Draw a square with one rounded corner, can be centered on the arc centre, when `center` is `true`.
|
||||||
h = is_list(w) ? w.y : w;
|
h = is_list(w) ? w.y : w;
|
||||||
w = is_list(w) ? w.x : w;
|
w = is_list(w) ? w.x : w;
|
||||||
offset_w = center ? r - w : 0;
|
offset_w = center ? r - w : 0;
|
||||||
|
|
|
@ -40,7 +40,7 @@ module rounded_corner(r, h, r2, ir = 0) { //! 2D version
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module rounded_cylinder(r, h, r2, ir = 0, angle = 360) //! Rounded cylinder given radius ```r```, height ```h```, optional internal radius ```ir``` and optional ```angle```
|
module rounded_cylinder(r, h, r2, ir = 0, angle = 360) //! Rounded cylinder given radius `r`, height `h`, optional internal radius `ir` and optional `angle`
|
||||||
{
|
{
|
||||||
rotate_extrude(angle = angle)
|
rotate_extrude(angle = angle)
|
||||||
rounded_corner(r, h, r2, ir);
|
rounded_corner(r, h, r2, ir);
|
||||||
|
|
|
@ -48,7 +48,7 @@ function rounded_polygon_tangents(points) = //! Compute the straight sections ne
|
||||||
function sumv(v, i = 0, sum = 0) = i == len(v) ? sum : sumv(v, i + 1, sum + v[i]);
|
function sumv(v, i = 0, sum = 0) = i == len(v) ? sum : sumv(v, i + 1, sum + v[i]);
|
||||||
|
|
||||||
// the cross product of 2D vectors is the area of the parallelogram between them. We use the sign of this to decide if the angle is bigger than 180.
|
// the cross product of 2D vectors is the area of the parallelogram between them. We use the sign of this to decide if the angle is bigger than 180.
|
||||||
function rounded_polygon_length(points, tangents) = //! Calculate the length given the point list and the list of tangents computed by ``` rounded_polygon_tangents```
|
function rounded_polygon_length(points, tangents) = //! Calculate the length given the point list and the list of tangents computed by ` rounded_polygon_tangents`
|
||||||
let(
|
let(
|
||||||
len = len(points),
|
len = len(points),
|
||||||
indices = [0 : len - 1],
|
indices = [0 : len - 1],
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
//
|
//
|
||||||
include <../utils/core/core.scad>
|
include <../utils/core/core.scad>
|
||||||
|
|
||||||
module sector(r, start_angle, end_angle) { //! Create specified sector given radius ```r```, ```start_angle``` and ```end_angle```
|
module sector(r, start_angle, end_angle) { //! Create specified sector given radius `r`, `start_angle` and `end_angle`
|
||||||
R = r * sqrt(2) + 1;
|
R = r * sqrt(2) + 1;
|
||||||
|
|
||||||
if(end_angle > start_angle)
|
if(end_angle > start_angle)
|
||||||
|
|
|
@ -172,10 +172,10 @@ function arc_points(r, a = [90, 0, 180], al = 90) = //! Generate the points of a
|
||||||
let(sides = ceil(r2sides(r) * al / 360), tf = rotate(a))
|
let(sides = ceil(r2sides(r) * al / 360), tf = rotate(a))
|
||||||
[for(i = [0 : sides]) let(t = i * al / sides) transform([r * sin(t), r * cos(t), 0], tf)];
|
[for(i = [0 : sides]) let(t = i * al / sides) transform([r * sin(t), r * cos(t), 0], tf)];
|
||||||
|
|
||||||
function before(path1, path2) = //! Translate ```path1``` so its end meets the start of ```path2``` and then concatenate
|
function before(path1, path2) = //! Translate `path1` so its end meets the start of `path2` and then concatenate
|
||||||
let(end = len(path1) - 1, offset = path2[0] - path1[end])
|
let(end = len(path1) - 1, offset = path2[0] - path1[end])
|
||||||
concat([for(i = [0 : end - 1]) path1[i] + offset], path2);
|
concat([for(i = [0 : end - 1]) path1[i] + offset], path2);
|
||||||
|
|
||||||
function after(path1, path2) = //! Translate ```path2``` so its start meets the end of ```path1``` and then concatenate
|
function after(path1, path2) = //! Translate `path2` so its start meets the end of `path1` and then concatenate
|
||||||
let(end1 = len(path1) - 1, end2 = len(path2) - 1, offset = path1[end1] - path2[0])
|
let(end1 = len(path1) - 1, end2 = len(path2) - 1, offset = path1[end1] - path2[0])
|
||||||
concat(path1, [for(i = [1 : end2]) path2[i] + offset]);
|
concat(path1, [for(i = [1 : end2]) path2[i] + offset]);
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
//
|
//
|
||||||
//! Utilities for making threads with sweep. They can be used to model screws, nuts, studding, leadscrews, etc, and also to make printed threads.
|
//! Utilities for making threads with sweep. They can be used to model screws, nuts, studding, leadscrews, etc, and also to make printed threads.
|
||||||
//!
|
//!
|
||||||
//! The ends can be tapered, flat or chamfered by setting the ```top``` and ```bot``` parameters to -1 for tapered, 0 for a flat cut and positive to
|
//! The ends can be tapered, flat or chamfered by setting the `top` and `bot` parameters to -1 for tapered, 0 for a flat cut and positive to
|
||||||
//! specify a chamfer angle.
|
//! specify a chamfer angle.
|
||||||
//!
|
//!
|
||||||
//! Threads are by default solid, so the male version is wrapped around a cylinder and the female inside a tube. This can be suppressed to just get the helix, for
|
//! Threads are by default solid, so the male version is wrapped around a cylinder and the female inside a tube. This can be suppressed to just get the helix, for
|
||||||
|
@ -32,8 +32,8 @@
|
||||||
//! a cylinder. To get around this a colour can be passed to thread that is used to colour the cylinder and then toned down to colour the helix.
|
//! a cylinder. To get around this a colour can be passed to thread that is used to colour the cylinder and then toned down to colour the helix.
|
||||||
//!
|
//!
|
||||||
//! Making the ends requires a CGAL intersection, which make threads relatively slow. For this reason they are generally disabled when using the GUI but can
|
//! Making the ends requires a CGAL intersection, which make threads relatively slow. For this reason they are generally disabled when using the GUI but can
|
||||||
//! be enabled by setting ```$show_threads``` to ```true```. When the tests are run, by default, threads are enabled only for things that feature them like screws.
|
//! be enabled by setting `$show_threads` to `true`. When the tests are run, by default, threads are enabled only for things that feature them like screws.
|
||||||
//! This behaviour can be changed by setting a ```NOPSCADLIB_SHOW_THREADS``` environment variable to ```false``` to disable all threads and ```true``` to enable all threads.
|
//! This behaviour can be changed by setting a `NOPSCADLIB_SHOW_THREADS` environment variable to `false` to disable all threads and `true` to enable all threads.
|
||||||
//! The same variable also affects the generation of assembly diagrams.
|
//! The same variable also affects the generation of assembly diagrams.
|
||||||
//!
|
//!
|
||||||
//! Threads obey the $fn, $fa, $fs variables.
|
//! Threads obey the $fn, $fa, $fs variables.
|
||||||
|
|
|
@ -28,11 +28,11 @@ module ring(or, ir) //! Create a ring with specified external and internal radii
|
||||||
circle4n(ir);
|
circle4n(ir);
|
||||||
}
|
}
|
||||||
|
|
||||||
module tube(or, ir, h, center = true) //! Create a tube with specified external and internal radii and height ```h```
|
module tube(or, ir, h, center = true) //! Create a tube with specified external and internal radii and height `h`
|
||||||
linear_extrude(h, center = center, convexity = 5)
|
linear_extrude(h, center = center, convexity = 5)
|
||||||
ring(or, ir);
|
ring(or, ir);
|
||||||
|
|
||||||
module woven_tube(or, ir, h, center= true, colour = grey(30), colour2, warp = 2, weft) {//! Create a woven tube with specified external and internal radii, height ```h```, colours, warp and weft
|
module woven_tube(or, ir, h, center= true, colour = grey(30), colour2, warp = 2, weft) {//! Create a woven tube with specified external and internal radii, height `h`, colours, warp and weft
|
||||||
colour2 = colour2 ? colour2 : colour * 0.8;
|
colour2 = colour2 ? colour2 : colour * 0.8;
|
||||||
weft = weft ? weft : warp;
|
weft = weft ? weft : warp;
|
||||||
warp_count = max(floor(PI * or / warp), 0.5);
|
warp_count = max(floor(PI * or / warp), 0.5);
|
||||||
|
@ -68,4 +68,3 @@ module woven_tube(or, ir, h, center= true, colour = grey(30), colour2, warp = 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,7 +74,7 @@ module orientate_axial(length, height, pitch, wire_d) { // Orient horizontal or
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module ax_res(type, value, tol = 5, pitch = 0) { //! Through hole axial resistor. If ```pitch``` is zero the minimum is used. If below the minimum the resistor is placed vertical.
|
module ax_res(type, value, tol = 5, pitch = 0) { //! Through hole axial resistor. If `pitch` is zero the minimum is used. If below the minimum the resistor is placed vertical.
|
||||||
vitamin(str("ax_res(", type[0], ", ", value, arg(tol, 5, "tol"), "): Resistor ", value, " Ohms ", tol, "% ",ax_res_wattage(type), "W"));
|
vitamin(str("ax_res(", type[0], ", ", value, arg(tol, 5, "tol"), "): Resistor ", value, " Ohms ", tol, "% ",ax_res_wattage(type), "W"));
|
||||||
|
|
||||||
wire_d = ax_res_wire(type);
|
wire_d = ax_res_wire(type);
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
//! To make the back of the belt run against a smooth pulley on the outside of the loop specify a negative pitch radius.
|
//! To make the back of the belt run against a smooth pulley on the outside of the loop specify a negative pitch radius.
|
||||||
//!
|
//!
|
||||||
//! By default the path is a closed loop but a gap length and position can be specified to make open loops.
|
//! By default the path is a closed loop but a gap length and position can be specified to make open loops.
|
||||||
//! To draw the gap its XY position is specified by ```gap_pos```. ```gap_pos.z``` can be used to specify a rotation if the gap is not at the bottom of the loop.
|
//! To draw the gap its XY position is specified by `gap_pos`. `gap_pos.z` can be used to specify a rotation if the gap is not at the bottom of the loop.
|
||||||
//!
|
//!
|
||||||
//! Individual teeth are not drawn, instead they are represented by a lighter colour.
|
//! Individual teeth are not drawn, instead they are represented by a lighter colour.
|
||||||
//
|
//
|
||||||
|
|
|
@ -209,7 +209,7 @@ module al_clad_resistor_assembly(type, value, sleeved = true) { //* Draw alumini
|
||||||
|
|
||||||
function TO220_thickness() = 1.5; //! Thickness of the tab of a TO220
|
function TO220_thickness() = 1.5; //! Thickness of the tab of a TO220
|
||||||
|
|
||||||
module TO220(description, leads = 3, lead_length = 16) { //! Draw a TO220 package, use ```description``` to describe what it is
|
module TO220(description, leads = 3, lead_length = 16) { //! Draw a TO220 package, use `description` to describe what it is
|
||||||
width = 10.2;
|
width = 10.2;
|
||||||
inset = 1.5;
|
inset = 1.5;
|
||||||
hole = 3.3;
|
hole = 3.3;
|
||||||
|
|
|
@ -122,7 +122,7 @@ module fan_hole_positions(type, z = undef) { //! Position children at the screw
|
||||||
children();
|
children();
|
||||||
}
|
}
|
||||||
|
|
||||||
module fan_holes(type, poly = false, screws = true, h = 100) { //! Make all the holes for the fan, or just the aperture if ```screws``` is false. Set ```poly``` true for poly_holes.
|
module fan_holes(type, poly = false, screws = true, h = 100) { //! Make all the holes for the fan, or just the aperture if `screws` is false. Set `poly` true for poly_holes.
|
||||||
hole_pitch = fan_hole_pitch(type);
|
hole_pitch = fan_hole_pitch(type);
|
||||||
screw = fan_screw(type);
|
screw = fan_screw(type);
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ module insert(type) { //! Draw specified insert
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module insert_hole(type, counterbore = 0, horizontal = false) { //! Make a hole to take an insert, ```counterbore``` is the extra length for the screw
|
module insert_hole(type, counterbore = 0, horizontal = false) { //! Make a hole to take an insert, `counterbore` is the extra length for the screw
|
||||||
h = insert_hole_length(type);
|
h = insert_hole_length(type);
|
||||||
|
|
||||||
render(convexity = 2)
|
render(convexity = 2)
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
//! LED strip lights that can be cut to size.
|
//! LED strip lights that can be cut to size.
|
||||||
//!
|
//!
|
||||||
//! The definitions are for the full length but they can be cut to size by specifying how many segments,
|
//! The definitions are for the full length but they can be cut to size by specifying how many segments,
|
||||||
//! which can by calcuated using ```light_strip_segments(type, max_length)```.
|
//! which can by calcuated using `light_strip_segments(type, max_length)`.
|
||||||
//!
|
//!
|
||||||
//! The `light_strip_clip()` module makes a clip to go around the light that can be incorporated into a printed bracket to hold it.
|
//! The `light_strip_clip()` module makes a clip to go around the light that can be incorporated into a printed bracket to hold it.
|
||||||
//
|
//
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
//
|
//
|
||||||
//! Microview OLED display with on board AVR by geekammo / Sparkfun.
|
//! Microview OLED display with on board AVR by geekammo / Sparkfun.
|
||||||
//!
|
//!
|
||||||
//! ```microview()``` generates the model. ```microview(true)``` makes an object to cut out a panel aperture for it.
|
//! `microview()` generates the model. `microview(true)` makes an object to cut out a panel aperture for it.
|
||||||
//!
|
//!
|
||||||
//! Uses STL files copyright geekammo and licenced with MIT license, see [microview/LICENSE.txt](vitamins/microview/LICENSE.txt).
|
//! Uses STL files copyright geekammo and licenced with MIT license, see [microview/LICENSE.txt](vitamins/microview/LICENSE.txt).
|
||||||
//
|
//
|
||||||
|
|
|
@ -20,12 +20,12 @@
|
||||||
//
|
//
|
||||||
//! Nitrile rubber O-rings.
|
//! Nitrile rubber O-rings.
|
||||||
//!
|
//!
|
||||||
//! Just a black torus specified by internal diameter, ```id``` and ```minor_d``` plus a BOM entry.
|
//! Just a black torus specified by internal diameter, `id` and `minor_d` plus a BOM entry.
|
||||||
//! Can be shown stretched by specifying the ```actual_id```.
|
//! Can be shown stretched by specifying the `actual_id`.
|
||||||
//
|
//
|
||||||
include <../utils/core/core.scad>
|
include <../utils/core/core.scad>
|
||||||
|
|
||||||
module O_ring(id, minor_d, actual_id = 0) { //! Draw O-ring with specified internal diameter and minor diameter. ```actual_id``` can be used to stretch it around something.
|
module O_ring(id, minor_d, actual_id = 0) { //! Draw O-ring with specified internal diameter and minor diameter. `actual_id` can be used to stretch it around something.
|
||||||
vitamin(str("O_ring(", id, ", ", minor_d, "): O-ring nitrile ", id, "mm x ", minor_d, "mm"));
|
vitamin(str("O_ring(", id, ", ", minor_d, "): O-ring nitrile ", id, "mm x ", minor_d, "mm"));
|
||||||
|
|
||||||
D = actual_id > id ? actual_id : id; // allow it to be stretched
|
D = actual_id > id ? actual_id : id; // allow it to be stretched
|
||||||
|
|
|
@ -47,7 +47,7 @@ function carriage_pitch_y(type) = type[6]; //! Screw hole y pitch
|
||||||
function carriage_screw(type) = type[7]; //! Carriage screw type
|
function carriage_screw(type) = type[7]; //! Carriage screw type
|
||||||
function carriage_screw_depth(type) = 2 * screw_radius(carriage_screw(type)); //! Carriage thread depth
|
function carriage_screw_depth(type) = 2 * screw_radius(carriage_screw(type)); //! Carriage thread depth
|
||||||
|
|
||||||
function rail_holes(type, length) = //! Number of holes in a rail given its ```length```
|
function rail_holes(type, length) = //! Number of holes in a rail given its `length`
|
||||||
floor((length - 2 * rail_end(type)) / rail_pitch(type)) + 1;
|
floor((length - 2 * rail_end(type)) / rail_pitch(type)) + 1;
|
||||||
|
|
||||||
module rail_hole_positions(type, length, first = 0, screws = 100, both_ends = true) { //! Position children over screw holes
|
module rail_hole_positions(type, length, first = 0, screws = 100, both_ends = true) { //! Position children over screw holes
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
//
|
//
|
||||||
//! Machine screws and wood screws with various head styles.
|
//! Machine screws and wood screws with various head styles.
|
||||||
//!
|
//!
|
||||||
//! For an explanation of ```screw_polysink()``` see <https://hydraraptor.blogspot.com/2020/12/sinkholes.html>.
|
//! For an explanation of `screw_polysink()` see <https://hydraraptor.blogspot.com/2020/12/sinkholes.html>.
|
||||||
//
|
//
|
||||||
include <../utils/core/core.scad>
|
include <../utils/core/core.scad>
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ module scs_bearing_block(type) { //! Draw the specified SCS bearing block
|
||||||
bearing = scs_bearing(type);
|
bearing = scs_bearing(type);
|
||||||
clip = scs_circlip(type);
|
clip = scs_circlip(type);
|
||||||
|
|
||||||
module right_trapezoid(base, top, height, h = 0, center = true) {//! A right angled trapezoid with the 90° corner at the origin. 3D when ```h``` is nonzero, otherwise 2D
|
module right_trapezoid(base, top, height, h = 0, center = true) {//! A right angled trapezoid with the 90° corner at the origin. 3D when `h` is nonzero, otherwise 2D
|
||||||
extrude_if(h, center = center)
|
extrude_if(h, center = center)
|
||||||
polygon(points = [ [0,0], [base, 0], [top, height], [0, height] ]);
|
polygon(points = [ [0,0], [base, 0], [top, height], [0, height] ]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ function smd_100th(x) = //! Convert dimension to 1/100" notation
|
||||||
function smd_size(size) = //! Convert size to 1/100" notation
|
function smd_size(size) = //! Convert size to 1/100" notation
|
||||||
str(smd_100th(size.x), smd_100th(size.y));
|
str(smd_100th(size.x), smd_100th(size.y));
|
||||||
|
|
||||||
module smd_led(type, colour, cutout) { //! Draw an SMD LED with specified ```colour```
|
module smd_led(type, colour, cutout) { //! Draw an SMD LED with specified `colour`
|
||||||
size = smd_led_size(type);
|
size = smd_led_size(type);
|
||||||
vitamin(str("smd_led(", type[0], ", ", colour, "): SMD LED ", smd_size(size), " ", colour));
|
vitamin(str("smd_led(", type[0], ", ", colour, "): SMD LED ", smd_size(size), " ", colour));
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ module cable_tie_holes(cable_r, h = 100) { //! Holes to thread a ziptie through
|
||||||
drill(r, 0);
|
drill(r, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
module cable_tie(cable_r, thickness) { //! A ziptie threaded around cable radius ```cable_r``` and through a panel with specified ```thickness```.
|
module cable_tie(cable_r, thickness) { //! A ziptie threaded around cable radius `cable_r` and through a panel with specified `thickness`.
|
||||||
translate_z(cable_r)
|
translate_z(cable_r)
|
||||||
rotate([-90, 0, 90])
|
rotate([-90, 0, 90])
|
||||||
ziptie(small_ziptie, cable_r, thickness);
|
ziptie(small_ziptie, cable_r, thickness);
|
||||||
|
|
|
@ -30,7 +30,7 @@ function ziptie_latch(type) = type[3]; //! Latch dimensions
|
||||||
function ziptie_colour(type) = type[4]; //! Colour
|
function ziptie_colour(type) = type[4]; //! Colour
|
||||||
function ziptie_tail(type) = type[5]; //! The length without teeth
|
function ziptie_tail(type) = type[5]; //! The length without teeth
|
||||||
|
|
||||||
module ziptie(type, r, t = 0) //! Draw specified ziptie wrapped around radius ```r``` and optionally through panel thickness ```t```
|
module ziptie(type, r, t = 0) //! Draw specified ziptie wrapped around radius `r` and optionally through panel thickness `t`
|
||||||
{
|
{
|
||||||
latch = ziptie_latch(type);
|
latch = ziptie_latch(type);
|
||||||
lx = latch.x / 2;
|
lx = latch.x / 2;
|
||||||
|
|
Loading…
Reference in New Issue