pybosl2 0.5.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pybosl2-0.5.0/LICENSE +24 -0
- pybosl2-0.5.0/PKG-INFO +130 -0
- pybosl2-0.5.0/README.md +96 -0
- pybosl2-0.5.0/bosl2/__init__.py +46 -0
- pybosl2-0.5.0/bosl2/_mctable.py +127 -0
- pybosl2-0.5.0/bosl2/ball_bearings.py +142 -0
- pybosl2-0.5.0/bosl2/beziers.py +778 -0
- pybosl2-0.5.0/bosl2/bottlecaps.py +229 -0
- pybosl2-0.5.0/bosl2/color.py +198 -0
- pybosl2-0.5.0/bosl2/comparisons.py +36 -0
- pybosl2-0.5.0/bosl2/constants.py +105 -0
- pybosl2-0.5.0/bosl2/cubetruss.py +391 -0
- pybosl2-0.5.0/bosl2/distributors.py +554 -0
- pybosl2-0.5.0/bosl2/drawing.py +712 -0
- pybosl2-0.5.0/bosl2/gears.py +876 -0
- pybosl2-0.5.0/bosl2/geometry.py +155 -0
- pybosl2-0.5.0/bosl2/hinges.py +134 -0
- pybosl2-0.5.0/bosl2/isosurface.py +457 -0
- pybosl2-0.5.0/bosl2/joiners.py +113 -0
- pybosl2-0.5.0/bosl2/linear_bearings.py +126 -0
- pybosl2-0.5.0/bosl2/masking.py +403 -0
- pybosl2-0.5.0/bosl2/math.py +154 -0
- pybosl2-0.5.0/bosl2/miscellaneous.py +417 -0
- pybosl2-0.5.0/bosl2/modular_hose.py +144 -0
- pybosl2-0.5.0/bosl2/nema_steppers.py +131 -0
- pybosl2-0.5.0/bosl2/nurbs.py +480 -0
- pybosl2-0.5.0/bosl2/partitions.py +541 -0
- pybosl2-0.5.0/bosl2/paths.py +1554 -0
- pybosl2-0.5.0/bosl2/polyhedra.py +179 -0
- pybosl2-0.5.0/bosl2/regions.py +115 -0
- pybosl2-0.5.0/bosl2/rounding.py +299 -0
- pybosl2-0.5.0/bosl2/screw_drive.py +348 -0
- pybosl2-0.5.0/bosl2/screws.py +431 -0
- pybosl2-0.5.0/bosl2/shapes2d.py +1508 -0
- pybosl2-0.5.0/bosl2/shapes3d.py +3062 -0
- pybosl2-0.5.0/bosl2/skin.py +735 -0
- pybosl2-0.5.0/bosl2/sliders.py +124 -0
- pybosl2-0.5.0/bosl2/threading.py +327 -0
- pybosl2-0.5.0/bosl2/transforms.py +189 -0
- pybosl2-0.5.0/bosl2/vectors.py +61 -0
- pybosl2-0.5.0/bosl2/version.py +89 -0
- pybosl2-0.5.0/bosl2/vnf.py +289 -0
- pybosl2-0.5.0/bosl2/walls.py +269 -0
- pybosl2-0.5.0/pybosl2.egg-info/PKG-INFO +130 -0
- pybosl2-0.5.0/pybosl2.egg-info/SOURCES.txt +104 -0
- pybosl2-0.5.0/pybosl2.egg-info/dependency_links.txt +1 -0
- pybosl2-0.5.0/pybosl2.egg-info/requires.txt +11 -0
- pybosl2-0.5.0/pybosl2.egg-info/top_level.txt +2 -0
- pybosl2-0.5.0/pyproject.toml +65 -0
- pybosl2-0.5.0/pysolidfive/__init__.py +246 -0
- pybosl2-0.5.0/pysolidfive/_constants.py +80 -0
- pybosl2-0.5.0/pysolidfive/_edges.py +181 -0
- pybosl2-0.5.0/pysolidfive/docs/_ext/__init__.py +0 -0
- pybosl2-0.5.0/pysolidfive/docs/_ext/pythonscad_example.py +128 -0
- pybosl2-0.5.0/pysolidfive/docs/conf.py +85 -0
- pybosl2-0.5.0/pysolidfive/joiners.py +236 -0
- pybosl2-0.5.0/pysolidfive/paths.py +803 -0
- pybosl2-0.5.0/pysolidfive/shapes2d.py +445 -0
- pybosl2-0.5.0/pysolidfive/shapes3d.py +1744 -0
- pybosl2-0.5.0/pysolidfive/tests/__init__.py +34 -0
- pybosl2-0.5.0/pysolidfive/tests/mock_libfive.py +421 -0
- pybosl2-0.5.0/pysolidfive/tests/render_pysolidfive.py +246 -0
- pybosl2-0.5.0/pysolidfive/tests/test_pysolidfive.py +1116 -0
- pybosl2-0.5.0/pysolidfive/tests/test_pysolidfive_render.py +171 -0
- pybosl2-0.5.0/setup.cfg +4 -0
- pybosl2-0.5.0/tests/test_ball_bearings.py +64 -0
- pybosl2-0.5.0/tests/test_beziers.py +233 -0
- pybosl2-0.5.0/tests/test_bottlecaps.py +69 -0
- pybosl2-0.5.0/tests/test_color.py +133 -0
- pybosl2-0.5.0/tests/test_comparisons.py +45 -0
- pybosl2-0.5.0/tests/test_constants.py +60 -0
- pybosl2-0.5.0/tests/test_cubetruss.py +129 -0
- pybosl2-0.5.0/tests/test_distributors.py +154 -0
- pybosl2-0.5.0/tests/test_drawing.py +242 -0
- pybosl2-0.5.0/tests/test_gears.py +300 -0
- pybosl2-0.5.0/tests/test_geometry.py +78 -0
- pybosl2-0.5.0/tests/test_hinges.py +50 -0
- pybosl2-0.5.0/tests/test_isosurface.py +139 -0
- pybosl2-0.5.0/tests/test_joiners.py +57 -0
- pybosl2-0.5.0/tests/test_linear_bearings.py +52 -0
- pybosl2-0.5.0/tests/test_masking.py +63 -0
- pybosl2-0.5.0/tests/test_math.py +92 -0
- pybosl2-0.5.0/tests/test_miscellaneous.py +127 -0
- pybosl2-0.5.0/tests/test_modular_hose.py +49 -0
- pybosl2-0.5.0/tests/test_native_ops.py +77 -0
- pybosl2-0.5.0/tests/test_nema_steppers.py +56 -0
- pybosl2-0.5.0/tests/test_nurbs.py +155 -0
- pybosl2-0.5.0/tests/test_partitions.py +133 -0
- pybosl2-0.5.0/tests/test_paths.py +295 -0
- pybosl2-0.5.0/tests/test_paths3d.py +142 -0
- pybosl2-0.5.0/tests/test_polyhedra.py +64 -0
- pybosl2-0.5.0/tests/test_regions.py +72 -0
- pybosl2-0.5.0/tests/test_rounding.py +128 -0
- pybosl2-0.5.0/tests/test_screw_drive.py +109 -0
- pybosl2-0.5.0/tests/test_screws.py +175 -0
- pybosl2-0.5.0/tests/test_shapes2d.py +155 -0
- pybosl2-0.5.0/tests/test_shapes3d.py +212 -0
- pybosl2-0.5.0/tests/test_skin.py +273 -0
- pybosl2-0.5.0/tests/test_sliders.py +45 -0
- pybosl2-0.5.0/tests/test_stl_render.py +965 -0
- pybosl2-0.5.0/tests/test_threading.py +121 -0
- pybosl2-0.5.0/tests/test_transforms.py +110 -0
- pybosl2-0.5.0/tests/test_vectors.py +56 -0
- pybosl2-0.5.0/tests/test_version.py +64 -0
- pybosl2-0.5.0/tests/test_vnf.py +115 -0
- pybosl2-0.5.0/tests/test_walls.py +79 -0
pybosl2-0.5.0/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
BSD 2-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, pinkfish
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
16
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
17
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
18
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
19
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
20
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
21
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
22
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
23
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
24
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
pybosl2-0.5.0/PKG-INFO
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pybosl2
|
|
3
|
+
Version: 0.5.0
|
|
4
|
+
Summary: Python ports of the BOSL2 OpenSCAD library for use with PythonSCAD
|
|
5
|
+
Author: pinkfish
|
|
6
|
+
License-Expression: BSD-2-Clause
|
|
7
|
+
Project-URL: Homepage, https://github.com/pinkfish/pybosl2
|
|
8
|
+
Project-URL: Repository, https://github.com/pinkfish/pybosl2
|
|
9
|
+
Keywords: 3d,openscad,pythonscad,bosl2,cad,3d-printing
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Manufacturing
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: numpy
|
|
25
|
+
Provides-Extra: test
|
|
26
|
+
Requires-Dist: pytest>=7; extra == "test"
|
|
27
|
+
Requires-Dist: numpy; extra == "test"
|
|
28
|
+
Requires-Dist: pythonscad; extra == "test"
|
|
29
|
+
Provides-Extra: docs
|
|
30
|
+
Requires-Dist: sphinx>=7; extra == "docs"
|
|
31
|
+
Requires-Dist: numpy; extra == "docs"
|
|
32
|
+
Requires-Dist: pythonscad; extra == "docs"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# pybosl2
|
|
36
|
+
|
|
37
|
+
Python ports of the [BOSL2](https://github.com/BelfrySCAD/BOSL2) OpenSCAD library,
|
|
38
|
+
for use with [PythonSCAD](https://pythonscad.org). The package is imported as
|
|
39
|
+
`bosl2`, with one module per wrapped/ported `.scad` file so each Python module can
|
|
40
|
+
be read side by side with its OpenSCAD source.
|
|
41
|
+
|
|
42
|
+
Most modules (constants, math, vectors, paths, shapes2d, …) are standalone pure-Python
|
|
43
|
+
ports that work in plain CPython. The modules that build native geometry
|
|
44
|
+
(`shapes3d`, `masking`, and the `.polygon()`/`.polyhedron()` boundaries) import the
|
|
45
|
+
`pythonscad`/`openscad` native modules at load time.
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install pybosl2
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
This pulls in `numpy`. To build native geometry you also need PythonSCAD:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install pythonscad
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Usage
|
|
60
|
+
|
|
61
|
+
Import by submodule (the `square`/`circle`/`cube`/`text` names intentionally shadow
|
|
62
|
+
the plain OpenSCAD builtins with BOSL2's anchor/spin/orient-aware versions, so the
|
|
63
|
+
package is deliberately not wildcard-re-exported):
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
import bosl2.shapes3d as s3
|
|
67
|
+
import bosl2.shapes2d as s2
|
|
68
|
+
|
|
69
|
+
part = s3.cuboid([20, 20, 10]).up(5)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Development & tests
|
|
73
|
+
|
|
74
|
+
The test-suite runs against a real, pip-installed `pythonscad` in a virtualenv:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
python -m venv .venv # create from outside the repo dir, or the local
|
|
78
|
+
# bosl2/math.py etc. can shadow stdlib modules
|
|
79
|
+
source .venv/bin/activate
|
|
80
|
+
pip install -e '.[test]' # installs pybosl2 + pytest + numpy + pythonscad
|
|
81
|
+
pytest
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The `[test]` extra installs the `pythonscad` wheel, which provides the real
|
|
85
|
+
`pythonscad`/`openscad` native modules the geometry code imports.
|
|
86
|
+
|
|
87
|
+
A small number of tests exercise the full **PythonSCAD app** rather than the pip
|
|
88
|
+
wheel:
|
|
89
|
+
|
|
90
|
+
- STL-render tests (`tests/test_stl_render.py`) drive the real PythonSCAD binary
|
|
91
|
+
in a subprocess to export and measure meshes. They skip unless a binary is found
|
|
92
|
+
(set `PYTHONSCAD_BIN`, or install the app to `/Applications`).
|
|
93
|
+
- App-only native ops (e.g. `roof()`) skip when the pip wheel does not provide them.
|
|
94
|
+
|
|
95
|
+
## `pysolidfive` (bundled separate package)
|
|
96
|
+
|
|
97
|
+
The repo also vendors [`pysolidfive`](pysolidfive/) — a small, self-contained
|
|
98
|
+
libfive / signed-distance-function shape library for PythonSCAD. It is a **separate
|
|
99
|
+
piece**: it does not depend on `bosl2`, ships in the same wheel as its own top-level
|
|
100
|
+
`pysolidfive` package, and keeps its own tests, docs, and `pyproject.toml`.
|
|
101
|
+
|
|
102
|
+
Its test-suite runs against the numeric `mock_libfive` stand-in bundled in
|
|
103
|
+
`pysolidfive/tests`, so it needs only `numpy` (no `pythonscad` wheel). It uses
|
|
104
|
+
`unittest` rather than `pytest` — the package eagerly `import libfive`s at load, which
|
|
105
|
+
is incompatible with pytest's package-based collection:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
cd pysolidfive/tests
|
|
109
|
+
python -m unittest discover -s . -t .
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Documentation
|
|
113
|
+
|
|
114
|
+
The API docs are built with Sphinx (autodoc + napoleon) straight from the module
|
|
115
|
+
docstrings:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
pip install -e '.[docs]'
|
|
119
|
+
make -C docs html # renders into wiki/
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
On push to `main`, the `docs` GitHub Actions workflow builds and publishes them to
|
|
123
|
+
**GitHub Pages** (enable Pages with *Settings → Pages → Source: GitHub Actions*).
|
|
124
|
+
Examples in the docs embed interactive 3-D STL viewers; the renders are cached under
|
|
125
|
+
`docs/_generated/` and `docs/_extra/_stl/` — commit those caches so the images appear
|
|
126
|
+
on Pages, since CI has no PythonSCAD binary to render them.
|
|
127
|
+
|
|
128
|
+
## License
|
|
129
|
+
|
|
130
|
+
BSD 2-Clause License — see [LICENSE](LICENSE).
|
pybosl2-0.5.0/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# pybosl2
|
|
2
|
+
|
|
3
|
+
Python ports of the [BOSL2](https://github.com/BelfrySCAD/BOSL2) OpenSCAD library,
|
|
4
|
+
for use with [PythonSCAD](https://pythonscad.org). The package is imported as
|
|
5
|
+
`bosl2`, with one module per wrapped/ported `.scad` file so each Python module can
|
|
6
|
+
be read side by side with its OpenSCAD source.
|
|
7
|
+
|
|
8
|
+
Most modules (constants, math, vectors, paths, shapes2d, …) are standalone pure-Python
|
|
9
|
+
ports that work in plain CPython. The modules that build native geometry
|
|
10
|
+
(`shapes3d`, `masking`, and the `.polygon()`/`.polyhedron()` boundaries) import the
|
|
11
|
+
`pythonscad`/`openscad` native modules at load time.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install pybosl2
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
This pulls in `numpy`. To build native geometry you also need PythonSCAD:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pip install pythonscad
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
Import by submodule (the `square`/`circle`/`cube`/`text` names intentionally shadow
|
|
28
|
+
the plain OpenSCAD builtins with BOSL2's anchor/spin/orient-aware versions, so the
|
|
29
|
+
package is deliberately not wildcard-re-exported):
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
import bosl2.shapes3d as s3
|
|
33
|
+
import bosl2.shapes2d as s2
|
|
34
|
+
|
|
35
|
+
part = s3.cuboid([20, 20, 10]).up(5)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Development & tests
|
|
39
|
+
|
|
40
|
+
The test-suite runs against a real, pip-installed `pythonscad` in a virtualenv:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
python -m venv .venv # create from outside the repo dir, or the local
|
|
44
|
+
# bosl2/math.py etc. can shadow stdlib modules
|
|
45
|
+
source .venv/bin/activate
|
|
46
|
+
pip install -e '.[test]' # installs pybosl2 + pytest + numpy + pythonscad
|
|
47
|
+
pytest
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The `[test]` extra installs the `pythonscad` wheel, which provides the real
|
|
51
|
+
`pythonscad`/`openscad` native modules the geometry code imports.
|
|
52
|
+
|
|
53
|
+
A small number of tests exercise the full **PythonSCAD app** rather than the pip
|
|
54
|
+
wheel:
|
|
55
|
+
|
|
56
|
+
- STL-render tests (`tests/test_stl_render.py`) drive the real PythonSCAD binary
|
|
57
|
+
in a subprocess to export and measure meshes. They skip unless a binary is found
|
|
58
|
+
(set `PYTHONSCAD_BIN`, or install the app to `/Applications`).
|
|
59
|
+
- App-only native ops (e.g. `roof()`) skip when the pip wheel does not provide them.
|
|
60
|
+
|
|
61
|
+
## `pysolidfive` (bundled separate package)
|
|
62
|
+
|
|
63
|
+
The repo also vendors [`pysolidfive`](pysolidfive/) — a small, self-contained
|
|
64
|
+
libfive / signed-distance-function shape library for PythonSCAD. It is a **separate
|
|
65
|
+
piece**: it does not depend on `bosl2`, ships in the same wheel as its own top-level
|
|
66
|
+
`pysolidfive` package, and keeps its own tests, docs, and `pyproject.toml`.
|
|
67
|
+
|
|
68
|
+
Its test-suite runs against the numeric `mock_libfive` stand-in bundled in
|
|
69
|
+
`pysolidfive/tests`, so it needs only `numpy` (no `pythonscad` wheel). It uses
|
|
70
|
+
`unittest` rather than `pytest` — the package eagerly `import libfive`s at load, which
|
|
71
|
+
is incompatible with pytest's package-based collection:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
cd pysolidfive/tests
|
|
75
|
+
python -m unittest discover -s . -t .
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Documentation
|
|
79
|
+
|
|
80
|
+
The API docs are built with Sphinx (autodoc + napoleon) straight from the module
|
|
81
|
+
docstrings:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install -e '.[docs]'
|
|
85
|
+
make -C docs html # renders into wiki/
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
On push to `main`, the `docs` GitHub Actions workflow builds and publishes them to
|
|
89
|
+
**GitHub Pages** (enable Pages with *Settings → Pages → Source: GitHub Actions*).
|
|
90
|
+
Examples in the docs embed interactive 3-D STL viewers; the renders are cached under
|
|
91
|
+
`docs/_generated/` and `docs/_extra/_stl/` — commit those caches so the images appear
|
|
92
|
+
on Pages, since CI has no PythonSCAD binary to render them.
|
|
93
|
+
|
|
94
|
+
## License
|
|
95
|
+
|
|
96
|
+
BSD 2-Clause License — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Copyright (c) 2026, pinkfish
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the BSD 2-Clause License. See the LICENSE file in the project
|
|
4
|
+
# root for the full license text.
|
|
5
|
+
# SPDX-License-Identifier: BSD-2-Clause
|
|
6
|
+
|
|
7
|
+
# LibFile: bosl2/__init__.py
|
|
8
|
+
# Python ports of the BOSL2 OpenSCAD library, one file per wrapped/ported
|
|
9
|
+
# .scad file, so each Python file can be read side by side with its .scad
|
|
10
|
+
# source:
|
|
11
|
+
# bosl2/constants.py <- BOSL2/constants.scad (pure Python)
|
|
12
|
+
# bosl2/math.py <- BOSL2/math.scad (pure Python)
|
|
13
|
+
# bosl2/vectors.py <- BOSL2/vectors.scad (pure Python)
|
|
14
|
+
# bosl2/lists.py <- BOSL2/lists.scad (pure Python)
|
|
15
|
+
# bosl2/comparisons.py <- BOSL2/comparisons.scad (pure Python)
|
|
16
|
+
# bosl2/geometry.py <- BOSL2/geometry.scad (pure Python, partial)
|
|
17
|
+
# bosl2/paths.py <- BOSL2/paths.scad (pure Python)
|
|
18
|
+
# bosl2/shapes2d.py <- BOSL2/shapes2d.scad (pure Python)
|
|
19
|
+
# bosl2/shapes3d.py <- BOSL2/shapes3d.scad (thin osuse() wrapper)
|
|
20
|
+
#
|
|
21
|
+
# shapes3d.py is a thin wrapper that forwards every call to BOSL2 already
|
|
22
|
+
# loaded via osuse() -- it only works inside the real PythonSCAD app.
|
|
23
|
+
# Every other file here, including shapes2d.py, is a real, standalone
|
|
24
|
+
# port with no osuse()/BOSL2 runtime dependency at all, so it works in
|
|
25
|
+
# plain Python (useful for testing) as well as inside PythonSCAD:
|
|
26
|
+
# shapes2d.py computes each shape's outline in pure Python and then
|
|
27
|
+
# builds it with direct openscad primitive calls (square()/circle()/
|
|
28
|
+
# polygon()/text()/hull()/.offset()) instead of delegating to BOSL2.
|
|
29
|
+
#
|
|
30
|
+
# Names like square(), circle(), cube() and text() in shapes2d/shapes3d
|
|
31
|
+
# intentionally shadow the plain OpenSCAD builtins with BOSL2's
|
|
32
|
+
# anchor/spin/orient-aware versions, so this package is always imported
|
|
33
|
+
# by submodule (`from bosl2 import shapes3d`) rather than re-exported
|
|
34
|
+
# with a wildcard here. Submodules are also deliberately NOT imported
|
|
35
|
+
# eagerly below: shapes3d.py calls osuse() at import time and would
|
|
36
|
+
# raise outside the real PythonSCAD app, which would otherwise break
|
|
37
|
+
# `from bosl2 import <pure-python-module>` too.
|
|
38
|
+
#
|
|
39
|
+
# FileSummary: BOSL2 library ports, one file per wrapped/ported .scad file.
|
|
40
|
+
# FileGroup: BOSL2
|
|
41
|
+
|
|
42
|
+
# Version metadata. version.py has no heavy/native imports, so exposing it here is
|
|
43
|
+
# safe despite the deliberate no-eager-submodule-import policy noted above.
|
|
44
|
+
from bosl2.version import Version, __version__, version # noqa: E402,F401
|
|
45
|
+
|
|
46
|
+
__all__ = ["Version", "version", "__version__"]
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Copyright (c) 2026, pinkfish
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the BSD 2-Clause License. See the LICENSE file in the project
|
|
4
|
+
# root for the full license text.
|
|
5
|
+
# SPDX-License-Identifier: BSD-2-Clause
|
|
6
|
+
|
|
7
|
+
# The standard Marching Cubes triangle table (Paul Bourke, "Polygonising a scalar field").
|
|
8
|
+
# TRI_TABLE[cubeindex] is a flat list of edge indices, in groups of three, terminated by -1;
|
|
9
|
+
# each group is one triangle whose vertices lie on those cube edges. Corner and edge numbering:
|
|
10
|
+
# corners: v0(0,0,0) v1(1,0,0) v2(1,1,0) v3(0,1,0) v4(0,0,1) v5(1,0,1) v6(1,1,1) v7(0,1,1)
|
|
11
|
+
# edges: 0:(0,1) 1:(1,2) 2:(2,3) 3:(3,0) 4:(4,5) 5:(5,6) 6:(6,7) 7:(7,4) 8:(0,4) 9:(1,5) 10:(2,6) 11:(3,7)
|
|
12
|
+
# cubeindex bit i is set when corner i is "inside" (below the isolevel).
|
|
13
|
+
|
|
14
|
+
EDGE_CORNERS = [(0, 1), (1, 2), (2, 3), (3, 0), (4, 5), (5, 6), (6, 7), (7, 4),
|
|
15
|
+
(0, 4), (1, 5), (2, 6), (3, 7)]
|
|
16
|
+
|
|
17
|
+
CORNER_OFFSETS = [(0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 1, 0),
|
|
18
|
+
(0, 0, 1), (1, 0, 1), (1, 1, 1), (0, 1, 1)]
|
|
19
|
+
|
|
20
|
+
TRI_TABLE = [
|
|
21
|
+
[], [0, 8, 3], [0, 1, 9], [1, 8, 3, 9, 8, 1], [1, 2, 10], [0, 8, 3, 1, 2, 10],
|
|
22
|
+
[9, 2, 10, 0, 2, 9], [2, 8, 3, 2, 10, 8, 10, 9, 8], [3, 11, 2], [0, 11, 2, 8, 11, 0],
|
|
23
|
+
[1, 9, 0, 2, 3, 11], [1, 11, 2, 1, 9, 11, 9, 8, 11], [3, 10, 1, 11, 10, 3],
|
|
24
|
+
[0, 10, 1, 0, 8, 10, 8, 11, 10], [3, 9, 0, 3, 11, 9, 11, 10, 9],
|
|
25
|
+
[9, 8, 10, 10, 8, 11], [4, 7, 8], [4, 3, 0, 7, 3, 4], [0, 1, 9, 8, 4, 7],
|
|
26
|
+
[4, 1, 9, 4, 7, 1, 7, 3, 1], [1, 2, 10, 8, 4, 7], [3, 4, 7, 3, 0, 4, 1, 2, 10],
|
|
27
|
+
[9, 2, 10, 9, 0, 2, 8, 4, 7], [2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4],
|
|
28
|
+
[8, 4, 7, 3, 11, 2], [11, 4, 7, 11, 2, 4, 2, 0, 4], [9, 0, 1, 8, 4, 7, 2, 3, 11],
|
|
29
|
+
[4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1], [3, 10, 1, 3, 11, 10, 7, 8, 4],
|
|
30
|
+
[1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4], [4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3],
|
|
31
|
+
[4, 7, 11, 4, 11, 9, 9, 11, 10], [9, 5, 4], [9, 5, 4, 0, 8, 3], [0, 5, 4, 1, 5, 0],
|
|
32
|
+
[8, 5, 4, 8, 3, 5, 3, 1, 5], [1, 2, 10, 9, 5, 4], [3, 0, 8, 1, 2, 10, 4, 9, 5],
|
|
33
|
+
[5, 2, 10, 5, 4, 2, 4, 0, 2], [2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8],
|
|
34
|
+
[9, 5, 4, 2, 3, 11], [0, 11, 2, 0, 8, 11, 4, 9, 5], [0, 5, 4, 0, 1, 5, 2, 3, 11],
|
|
35
|
+
[2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5], [10, 3, 11, 10, 1, 3, 9, 5, 4],
|
|
36
|
+
[4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10], [5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3],
|
|
37
|
+
[5, 4, 8, 5, 8, 10, 10, 8, 11], [9, 7, 8, 5, 7, 9], [9, 3, 0, 9, 5, 3, 5, 7, 3],
|
|
38
|
+
[0, 7, 8, 0, 1, 7, 1, 5, 7], [1, 5, 3, 3, 5, 7], [9, 7, 8, 9, 5, 7, 10, 1, 2],
|
|
39
|
+
[10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3], [8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2],
|
|
40
|
+
[2, 10, 5, 2, 5, 3, 3, 5, 7], [7, 9, 5, 7, 8, 9, 3, 11, 2],
|
|
41
|
+
[9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11], [2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7],
|
|
42
|
+
[11, 2, 1, 11, 1, 7, 7, 1, 5], [9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11],
|
|
43
|
+
[5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0],
|
|
44
|
+
[11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0], [11, 10, 5, 7, 11, 5],
|
|
45
|
+
[10, 6, 5], [0, 8, 3, 5, 10, 6], [9, 0, 1, 5, 10, 6], [1, 8, 3, 1, 9, 8, 5, 10, 6],
|
|
46
|
+
[1, 6, 5, 2, 6, 1], [1, 6, 5, 1, 2, 6, 3, 0, 8], [9, 6, 5, 9, 0, 6, 0, 2, 6],
|
|
47
|
+
[5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8], [2, 3, 11, 10, 6, 5],
|
|
48
|
+
[11, 0, 8, 11, 2, 0, 10, 6, 5], [0, 1, 9, 2, 3, 11, 5, 10, 6],
|
|
49
|
+
[5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11], [6, 3, 11, 6, 5, 3, 5, 1, 3],
|
|
50
|
+
[0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6], [3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9],
|
|
51
|
+
[6, 5, 9, 6, 9, 11, 11, 9, 8], [5, 10, 6, 4, 7, 8], [4, 3, 0, 4, 7, 3, 6, 5, 10],
|
|
52
|
+
[1, 9, 0, 5, 10, 6, 8, 4, 7], [10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4],
|
|
53
|
+
[6, 1, 2, 6, 5, 1, 4, 7, 8], [1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7],
|
|
54
|
+
[8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6], [7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9],
|
|
55
|
+
[3, 11, 2, 7, 8, 4, 10, 6, 5], [5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11],
|
|
56
|
+
[0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6],
|
|
57
|
+
[9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6],
|
|
58
|
+
[8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6],
|
|
59
|
+
[5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11],
|
|
60
|
+
[0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7],
|
|
61
|
+
[6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9], [10, 4, 9, 6, 4, 10],
|
|
62
|
+
[4, 10, 6, 4, 9, 10, 0, 8, 3], [10, 0, 1, 10, 6, 0, 6, 4, 0],
|
|
63
|
+
[8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10], [1, 4, 9, 1, 2, 4, 2, 6, 4],
|
|
64
|
+
[3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4], [0, 2, 4, 4, 2, 6],
|
|
65
|
+
[8, 3, 2, 8, 2, 4, 4, 2, 6], [10, 4, 9, 10, 6, 4, 11, 2, 3],
|
|
66
|
+
[0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6], [3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10],
|
|
67
|
+
[6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1], [9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3],
|
|
68
|
+
[8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1], [3, 11, 6, 3, 6, 0, 0, 6, 4],
|
|
69
|
+
[6, 4, 8, 11, 6, 8], [7, 10, 6, 7, 8, 10, 8, 9, 10], [0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10],
|
|
70
|
+
[10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0], [10, 6, 7, 10, 7, 1, 1, 7, 3],
|
|
71
|
+
[1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7], [2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9],
|
|
72
|
+
[7, 8, 0, 7, 0, 6, 6, 0, 2], [7, 3, 2, 6, 7, 2], [2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7],
|
|
73
|
+
[2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7],
|
|
74
|
+
[1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11], [11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1],
|
|
75
|
+
[8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6], [0, 9, 1, 11, 6, 7], [7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0],
|
|
76
|
+
[7, 11, 6], [7, 6, 11], [3, 0, 8, 11, 7, 6], [0, 1, 9, 11, 7, 6], [8, 1, 9, 8, 3, 1, 11, 7, 6],
|
|
77
|
+
[10, 1, 2, 6, 11, 7], [1, 2, 10, 3, 0, 8, 6, 11, 7], [2, 9, 0, 2, 10, 9, 6, 11, 7],
|
|
78
|
+
[6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8], [7, 2, 3, 6, 2, 7], [7, 0, 8, 7, 6, 0, 6, 2, 0],
|
|
79
|
+
[2, 7, 6, 2, 3, 7, 0, 1, 9], [1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6], [10, 7, 6, 10, 1, 7, 1, 3, 7],
|
|
80
|
+
[10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8], [0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7],
|
|
81
|
+
[7, 6, 10, 7, 10, 8, 8, 10, 9], [6, 8, 4, 11, 8, 6], [3, 6, 11, 3, 0, 6, 0, 4, 6],
|
|
82
|
+
[8, 6, 11, 8, 4, 6, 9, 0, 1], [9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6], [6, 8, 4, 6, 11, 8, 2, 10, 1],
|
|
83
|
+
[1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6], [4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9],
|
|
84
|
+
[10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3], [8, 2, 3, 8, 4, 2, 4, 6, 2],
|
|
85
|
+
[0, 4, 2, 4, 6, 2], [1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8], [1, 9, 4, 1, 4, 2, 2, 4, 6],
|
|
86
|
+
[8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1], [10, 1, 0, 10, 0, 6, 6, 0, 4],
|
|
87
|
+
[4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3], [10, 9, 4, 6, 10, 4], [4, 9, 5, 7, 6, 11],
|
|
88
|
+
[0, 8, 3, 4, 9, 5, 11, 7, 6], [5, 0, 1, 5, 4, 0, 7, 6, 11], [11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5],
|
|
89
|
+
[9, 5, 4, 10, 1, 2, 7, 6, 11], [6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5],
|
|
90
|
+
[7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2], [3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6],
|
|
91
|
+
[7, 2, 3, 7, 6, 2, 5, 4, 9], [9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7],
|
|
92
|
+
[3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0], [6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8],
|
|
93
|
+
[9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7], [1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4],
|
|
94
|
+
[4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10], [7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10],
|
|
95
|
+
[6, 9, 5, 6, 11, 9, 11, 8, 9], [3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5],
|
|
96
|
+
[0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11], [6, 11, 3, 6, 3, 5, 5, 3, 1],
|
|
97
|
+
[1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6], [0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10],
|
|
98
|
+
[11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5], [6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3],
|
|
99
|
+
[5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2], [9, 5, 6, 9, 6, 0, 0, 6, 2],
|
|
100
|
+
[1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8], [1, 5, 6, 2, 1, 6],
|
|
101
|
+
[1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6], [10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0],
|
|
102
|
+
[0, 3, 8, 5, 6, 10], [10, 5, 6], [11, 5, 10, 7, 5, 11], [11, 5, 10, 11, 7, 5, 8, 3, 0],
|
|
103
|
+
[5, 11, 7, 5, 10, 11, 1, 9, 0], [10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1],
|
|
104
|
+
[11, 1, 2, 11, 7, 1, 7, 5, 1], [0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11],
|
|
105
|
+
[9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7], [7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2],
|
|
106
|
+
[2, 5, 10, 2, 3, 5, 3, 7, 5], [8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5],
|
|
107
|
+
[9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2], [9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2],
|
|
108
|
+
[1, 3, 5, 3, 7, 5], [0, 8, 7, 0, 7, 1, 1, 7, 5], [9, 0, 3, 9, 3, 5, 5, 3, 7], [9, 8, 7, 5, 9, 7],
|
|
109
|
+
[5, 8, 4, 5, 10, 8, 10, 11, 8], [5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0],
|
|
110
|
+
[0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5], [10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4],
|
|
111
|
+
[2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8], [0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11],
|
|
112
|
+
[0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5], [9, 4, 5, 2, 11, 3],
|
|
113
|
+
[2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4], [5, 10, 2, 5, 2, 4, 4, 2, 0],
|
|
114
|
+
[3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9], [5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2],
|
|
115
|
+
[8, 4, 5, 8, 5, 3, 3, 5, 1], [0, 4, 5, 1, 0, 5], [8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5], [9, 4, 5],
|
|
116
|
+
[4, 11, 7, 4, 9, 11, 9, 10, 11], [0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11],
|
|
117
|
+
[1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11], [3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4],
|
|
118
|
+
[4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2], [9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3],
|
|
119
|
+
[11, 7, 4, 11, 4, 2, 2, 4, 0], [11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4],
|
|
120
|
+
[2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9], [9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7],
|
|
121
|
+
[3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10], [1, 10, 2, 8, 7, 4], [4, 9, 1, 4, 1, 7, 7, 1, 3],
|
|
122
|
+
[4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1], [4, 0, 3, 7, 4, 3], [4, 8, 7], [9, 10, 8, 10, 11, 8],
|
|
123
|
+
[3, 0, 9, 3, 9, 11, 11, 9, 10], [0, 1, 10, 0, 10, 8, 8, 10, 11], [3, 1, 10, 11, 3, 10],
|
|
124
|
+
[1, 2, 11, 1, 11, 9, 9, 11, 8], [3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9], [0, 2, 11, 8, 0, 11],
|
|
125
|
+
[3, 2, 11], [2, 3, 8, 2, 8, 10, 10, 8, 9], [9, 10, 2, 0, 9, 2], [2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8],
|
|
126
|
+
[1, 10, 2], [1, 3, 8, 9, 1, 8], [0, 9, 1], [0, 3, 8], [],
|
|
127
|
+
]
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Copyright (c) 2026, pinkfish
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the BSD 2-Clause License. See the LICENSE file in the project
|
|
4
|
+
# root for the full license text.
|
|
5
|
+
# SPDX-License-Identifier: BSD-2-Clause
|
|
6
|
+
|
|
7
|
+
# LibFile: bosl2/ball_bearings.py
|
|
8
|
+
# Pure-Python port of BOSL2's ball_bearings.scad: models of standard ball-bearing cartridges.
|
|
9
|
+
# :meth:`BallBearings.ball_bearing` builds a bearing -- either a sealed/shielded cartridge (nested
|
|
10
|
+
# rings plus a shield face) or an open one (inner and outer races, a ball-race groove, and the
|
|
11
|
+
# balls) -- from a trade-size name (``"608"``, ``"6902ZZ"``, ``"R8"``) or explicit id/od/width.
|
|
12
|
+
# :meth:`BallBearings.ball_bearing_info` returns the tabulated dimensions as a :class:`BearingSpec`.
|
|
13
|
+
#
|
|
14
|
+
# The trade-size table is transcribed verbatim from ball_bearings.scad.
|
|
15
|
+
#
|
|
16
|
+
# FileSummary: Standard ball-bearing cartridge models.
|
|
17
|
+
# FileGroup: BOSL2
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import math
|
|
22
|
+
import operator
|
|
23
|
+
from dataclasses import dataclass
|
|
24
|
+
from functools import reduce
|
|
25
|
+
|
|
26
|
+
from bosl2.constants import INCH
|
|
27
|
+
from bosl2.shapes3d import Bosl2Solid, tube, torus, sphere
|
|
28
|
+
|
|
29
|
+
__all__ = ["BallBearings", "BearingSpec"]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True)
|
|
33
|
+
class BearingSpec:
|
|
34
|
+
"""Dimensions of a standard ball-bearing cartridge (BOSL2 ball_bearing_info())."""
|
|
35
|
+
|
|
36
|
+
id: float # inner (shaft) diameter
|
|
37
|
+
od: float # outer diameter
|
|
38
|
+
width: float # axial width
|
|
39
|
+
shielded: bool # True for a sealed/shielded (ZZ) cartridge
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
_I = INCH
|
|
43
|
+
# trade size -> BearingSpec, transcribed from ball_bearings.scad.
|
|
44
|
+
_BEARINGS = {
|
|
45
|
+
"R2": BearingSpec(1 / 8 * _I, 3 / 8 * _I, 5 / 32 * _I, False),
|
|
46
|
+
"R3": BearingSpec(3 / 16 * _I, 1 / 2 * _I, 5 / 32 * _I, False),
|
|
47
|
+
"R4": BearingSpec(1 / 4 * _I, 5 / 8 * _I, 0.196 * _I, False),
|
|
48
|
+
"R6": BearingSpec(3 / 8 * _I, 7 / 8 * _I, 7 / 32 * _I, False),
|
|
49
|
+
"R8": BearingSpec(1 / 2 * _I, 9 / 8 * _I, 1 / 4 * _I, False),
|
|
50
|
+
"R10": BearingSpec(5 / 8 * _I, 11 / 8 * _I, 9 / 32 * _I, False),
|
|
51
|
+
"R12": BearingSpec(3 / 4 * _I, 13 / 8 * _I, 5 / 16 * _I, False),
|
|
52
|
+
"R14": BearingSpec(7 / 8 * _I, 15 / 8 * _I, 3 / 8 * _I, False),
|
|
53
|
+
"R16": BearingSpec(8 / 8 * _I, 16 / 8 * _I, 3 / 8 * _I, False),
|
|
54
|
+
"R18": BearingSpec(9 / 8 * _I, 17 / 8 * _I, 3 / 8 * _I, False),
|
|
55
|
+
"R20": BearingSpec(10 / 8 * _I, 18 / 8 * _I, 3 / 8 * _I, False),
|
|
56
|
+
"R22": BearingSpec(11 / 8 * _I, 20 / 8 * _I, 7 / 16 * _I, False),
|
|
57
|
+
"R24": BearingSpec(12 / 8 * _I, 21 / 8 * _I, 7 / 16 * _I, False),
|
|
58
|
+
"608": BearingSpec(8, 22, 7, False), "629": BearingSpec(9, 26, 8, False),
|
|
59
|
+
"635": BearingSpec(5, 19, 6, False), "6000": BearingSpec(10, 26, 8, False),
|
|
60
|
+
"6001": BearingSpec(12, 28, 8, False), "6002": BearingSpec(15, 32, 9, False),
|
|
61
|
+
"6003": BearingSpec(17, 35, 10, False), "6007": BearingSpec(35, 62, 14, False),
|
|
62
|
+
"6200": BearingSpec(10, 30, 9, False), "6201": BearingSpec(12, 32, 10, False),
|
|
63
|
+
"6202": BearingSpec(15, 35, 11, False), "6203": BearingSpec(17, 40, 12, False),
|
|
64
|
+
"6204": BearingSpec(20, 47, 14, False), "6205": BearingSpec(25, 52, 15, False),
|
|
65
|
+
"6206": BearingSpec(30, 62, 16, False), "6207": BearingSpec(35, 72, 17, False),
|
|
66
|
+
"6208": BearingSpec(40, 80, 18, False), "6209": BearingSpec(45, 85, 19, False),
|
|
67
|
+
"6210": BearingSpec(50, 90, 20, False), "6211": BearingSpec(55, 100, 21, False),
|
|
68
|
+
"6212": BearingSpec(60, 110, 22, False), "6301": BearingSpec(12, 37, 12, False),
|
|
69
|
+
"6302": BearingSpec(15, 42, 13, False), "6303": BearingSpec(17, 47, 14, False),
|
|
70
|
+
"6304": BearingSpec(20, 52, 15, False), "6305": BearingSpec(25, 62, 17, False),
|
|
71
|
+
"6306": BearingSpec(30, 72, 19, False), "6307": BearingSpec(35, 80, 21, False),
|
|
72
|
+
"6308": BearingSpec(40, 90, 23, False), "6309": BearingSpec(45, 100, 25, False),
|
|
73
|
+
"6310": BearingSpec(50, 110, 27, False), "6311": BearingSpec(55, 120, 29, False),
|
|
74
|
+
"6312": BearingSpec(60, 130, 31, False), "6403": BearingSpec(17, 62, 17, False),
|
|
75
|
+
"6800": BearingSpec(10, 19, 5, False), "6801": BearingSpec(12, 21, 5, False),
|
|
76
|
+
"6802": BearingSpec(15, 24, 5, False), "6803": BearingSpec(17, 26, 5, False),
|
|
77
|
+
"6804": BearingSpec(20, 32, 7, False), "6805": BearingSpec(25, 37, 7, False),
|
|
78
|
+
"6806": BearingSpec(30, 42, 7, False), "6900": BearingSpec(10, 22, 6, False),
|
|
79
|
+
"6901": BearingSpec(12, 24, 6, False), "6902": BearingSpec(15, 28, 7, False),
|
|
80
|
+
"6903": BearingSpec(17, 30, 7, False), "6904": BearingSpec(20, 37, 9, False),
|
|
81
|
+
"6905": BearingSpec(25, 42, 9, False), "6906": BearingSpec(30, 47, 9, False),
|
|
82
|
+
"6907": BearingSpec(35, 55, 10, False), "6908": BearingSpec(40, 62, 12, False),
|
|
83
|
+
"16002": BearingSpec(15, 22, 8, False), "16004": BearingSpec(20, 42, 8, False),
|
|
84
|
+
"16005": BearingSpec(25, 47, 8, False), "16100": BearingSpec(10, 28, 8, False),
|
|
85
|
+
"16101": BearingSpec(12, 30, 8, False),
|
|
86
|
+
}
|
|
87
|
+
# The "...ZZ" shielded variants share the open variant's dimensions.
|
|
88
|
+
_BEARINGS.update({
|
|
89
|
+
name + "ZZ": BearingSpec(s.id, s.od, s.width, True)
|
|
90
|
+
for name, s in list(_BEARINGS.items())
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class BallBearings:
|
|
95
|
+
"""Standard ball-bearing cartridge models (BOSL2 ball_bearings.scad)."""
|
|
96
|
+
|
|
97
|
+
@staticmethod
|
|
98
|
+
def ball_bearing_info(trade_size: str) -> BearingSpec:
|
|
99
|
+
"""The :class:`BearingSpec` for a standard trade size, e.g. ``"608"`` / ``"6902ZZ"`` / ``"R8"``."""
|
|
100
|
+
try:
|
|
101
|
+
return _BEARINGS[str(trade_size)]
|
|
102
|
+
except KeyError:
|
|
103
|
+
raise ValueError(f"Unsupported ball bearing trade size: {trade_size!r}")
|
|
104
|
+
|
|
105
|
+
@staticmethod
|
|
106
|
+
def ball_bearing(trade_size: str | None = None, id: float | None = None, od: float | None = None,
|
|
107
|
+
width: float | None = None, shield: bool = True, color: str | None = "silver",
|
|
108
|
+
_fn=None, _fa=None, _fs=None) -> Bosl2Solid:
|
|
109
|
+
"""A ball-bearing cartridge model (BOSL2 ball_bearing()).
|
|
110
|
+
|
|
111
|
+
Give a *trade_size* name, or explicit *id*/*od*/*width* (with *shield*). Returns a
|
|
112
|
+
:class:`~bosl2.shapes3d.Bosl2Solid` centered on the origin.
|
|
113
|
+
|
|
114
|
+
Examples:
|
|
115
|
+
A common 608 skate bearing:
|
|
116
|
+
|
|
117
|
+
.. pythonscad-example::
|
|
118
|
+
|
|
119
|
+
from bosl2.ball_bearings import BallBearings
|
|
120
|
+
BallBearings.ball_bearing("608").show()
|
|
121
|
+
"""
|
|
122
|
+
if trade_size is not None:
|
|
123
|
+
spec = BallBearings.ball_bearing_info(trade_size)
|
|
124
|
+
id, od, width, shield = spec.id, spec.od, spec.width, spec.shielded
|
|
125
|
+
assert None not in (id, od, width), "ball_bearing(): give a trade_size or id/od/width."
|
|
126
|
+
|
|
127
|
+
mid_d = (id + od) / 2
|
|
128
|
+
wall = (od - id) / 2 / 3
|
|
129
|
+
if shield:
|
|
130
|
+
result = (tube(id=id, wall=wall, h=width)
|
|
131
|
+
| tube(od=od, wall=wall, h=width)
|
|
132
|
+
| tube(id=id + 0.1, od=od - 0.1, h=(wall * 2 + width) / 2))
|
|
133
|
+
else:
|
|
134
|
+
ball_cnt = int(math.floor(math.pi * mid_d * 0.95 / (wall * 2)))
|
|
135
|
+
races = tube(id=id, wall=wall, h=width) | tube(od=od, wall=wall, h=width)
|
|
136
|
+
races = races - torus(r_maj=mid_d / 2, r_min=wall)
|
|
137
|
+
balls = reduce(operator.or_, (
|
|
138
|
+
sphere(d=wall * 2, _fn=_fn, _fa=_fa, _fs=_fs).right(mid_d / 2).rotate([0, 0, i * 360 / ball_cnt])
|
|
139
|
+
for i in range(ball_cnt)))
|
|
140
|
+
result = races | balls
|
|
141
|
+
result = Bosl2Solid(result.shape, size=[od, od, width])
|
|
142
|
+
return result.color(color) if color else result
|