compas-timber 2.2.0__tar.gz → 3.0.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.
- {compas_timber-2.2.0/src/compas_timber.egg-info → compas_timber-3.0.0}/PKG-INFO +40 -12
- {compas_timber-2.2.0 → compas_timber-3.0.0}/README.md +27 -10
- {compas_timber-2.2.0 → compas_timber-3.0.0}/pyproject.toml +48 -40
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/__init__.py +1 -1
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/base.py +52 -54
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/__init__.py +8 -2
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/ball_node.py +3 -1
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/butt_joint.py +37 -48
- compas_timber-3.0.0/src/compas_timber/connections/candidate_dispatch.py +74 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/cluster.py +24 -16
- compas_timber-3.0.0/src/compas_timber/connections/composite_joint.py +109 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/i_simple_scarf.py +0 -7
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/joint.py +59 -11
- compas_timber-3.0.0/src/compas_timber/connections/joint_candidate.py +213 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/l_butt.py +6 -6
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/l_french_ridge_lap.py +3 -8
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/l_lap.py +0 -4
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/l_miter.py +7 -93
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/l_tenon_mortise.py +2 -4
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/lap_joint.py +3 -9
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/mortise_tenon.py +0 -8
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/oligina.py +8 -6
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/panel_joint.py +1 -3
- compas_timber-3.0.0/src/compas_timber/connections/panel_layer_butt_joint.py +66 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/plate_joint.py +16 -1
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/plate_miter_joint.py +11 -1
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/solver.py +10 -5
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/t_birdsmouth.py +2 -8
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/t_butt.py +5 -2
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/t_dovetail.py +2 -8
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/t_lap.py +2 -6
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/t_step_joint.py +5 -9
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/t_tenon_mortise.py +2 -4
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/utilities.py +1 -95
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/x_lap.py +1 -5
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/x_notch.py +3 -8
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/y_butt.py +3 -8
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/elements/__init__.py +8 -8
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/elements/beam.py +8 -8
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/elements/fastener.py +0 -8
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/elements/fasteners/ball_node_fastener.py +6 -4
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/elements/fasteners/plate_fastener.py +6 -4
- compas_timber-3.0.0/src/compas_timber/elements/layer.py +522 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/elements/panel.py +113 -29
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/elements/plate.py +22 -22
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/elements/plate_geometry.py +92 -93
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/errors.py +19 -5
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/__init__.py +2 -0
- compas_timber-3.0.0/src/compas_timber/fabrication/basic_characters.zip +0 -0
- compas_timber-3.0.0/src/compas_timber/fabrication/birds_mouth.py +697 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/btlx.py +12 -19
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/double_cut.py +5 -4
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/dovetail_mortise.py +10 -6
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/dovetail_tenon.py +13 -7
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/drilling.py +8 -7
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/free_contour.py +4 -2
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/french_ridge_lap.py +16 -14
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/jack_cut.py +12 -6
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/lap.py +14 -14
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/longitudinal_cut.py +19 -6
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/mortise.py +10 -6
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/pocket.py +30 -14
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/simple_scarf.py +21 -27
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/slot.py +5 -4
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/step_joint.py +32 -15
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/step_joint_notch.py +19 -16
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/tenon.py +14 -8
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/fabrication/text.py +61 -15
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/geometry.py +141 -2
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/model.py +187 -85
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/panel_features/opening.py +4 -4
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/panel_features/panel_features.py +1 -1
- compas_timber-3.0.0/src/compas_timber/proto/__init__.py +0 -0
- compas_timber-3.0.0/src/compas_timber/proto/common_pb2.py +48 -0
- compas_timber-3.0.0/src/compas_timber/proto/common_pb2.pyi +67 -0
- compas_timber-3.0.0/src/compas_timber/proto/connections_pb2.py +109 -0
- compas_timber-3.0.0/src/compas_timber/proto/connections_pb2.pyi +757 -0
- compas_timber-3.0.0/src/compas_timber/proto/conversions.py +1001 -0
- compas_timber-3.0.0/src/compas_timber/proto/elements_pb2.py +85 -0
- compas_timber-3.0.0/src/compas_timber/proto/elements_pb2.pyi +284 -0
- compas_timber-3.0.0/src/compas_timber/proto/fabrication_pb2.py +97 -0
- compas_timber-3.0.0/src/compas_timber/proto/fabrication_pb2.pyi +786 -0
- compas_timber-3.0.0/src/compas_timber/proto/model_pb2.py +71 -0
- compas_timber-3.0.0/src/compas_timber/proto/model_pb2.pyi +172 -0
- compas_timber-3.0.0/src/compas_timber/proto/panel_features_pb2.py +42 -0
- compas_timber-3.0.0/src/compas_timber/proto/panel_features_pb2.pyi +57 -0
- compas_timber-3.0.0/src/compas_timber/proto/planning_pb2.py +59 -0
- compas_timber-3.0.0/src/compas_timber/proto/planning_pb2.pyi +176 -0
- compas_timber-3.0.0/src/compas_timber/proto/structural_pb2.py +43 -0
- compas_timber-3.0.0/src/compas_timber/proto/structural_pb2.pyi +35 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/rhino/__init__.py +1 -1
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/structural.py +6 -2
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/utils/r_tree.py +1 -1
- {compas_timber-2.2.0 → compas_timber-3.0.0/src/compas_timber.egg-info}/PKG-INFO +40 -12
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber.egg-info/SOURCES.txt +25 -1
- compas_timber-3.0.0/src/compas_timber.egg-info/entry_points.txt +2 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber.egg-info/requires.txt +9 -0
- compas_timber-2.2.0/src/compas_timber/connections/joint_candidate.py +0 -66
- compas_timber-2.2.0/src/compas_timber/elements/features.py +0 -238
- {compas_timber-2.2.0 → compas_timber-3.0.0}/LICENSE +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/setup.cfg +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/btlx/__init__.py +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/btlx/reader.py +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/panel_butt_joint.py +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/panel_miter_joint.py +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/connections/plate_butt_joint.py +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/elements/fasteners/__init__.py +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/panel_features/__init__.py +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/panel_features/panel_connection_interface.py +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/planning/__init__.py +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/planning/nesting.py +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/planning/sequencer.py +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/rhino/install.py +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber/utils/__init__.py +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber.egg-info/dependency_links.txt +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber.egg-info/not-zip-safe +0 -0
- {compas_timber-2.2.0 → compas_timber-3.0.0}/src/compas_timber.egg-info/top_level.txt +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: compas_timber
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.0
|
|
4
4
|
Summary: COMPAS package for modeling, designing and fabricating timber assemblies.
|
|
5
|
-
Author
|
|
5
|
+
Author: Aleksandra Anna Apolinarska, Chen Kasirer, Gonzalo Casas, Jonas Haldemann, Oliver Appling Bucklin, Aurèle L. Gheyselinck, Panayiotis Papacharalambous, Anastasiia Stryzhevska, Jelle Feringa, Joseph Kenny, Beverly Lytle, Eric Gozzi, Rodrigo Arca Zimmermann, Nicolas Benjamin Boscoboinik, Paul Jaeggi, Matthias Helmreich, Daniel Nunes Locatelli
|
|
6
6
|
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://gramaziokohler.github.io/compas_timber/latest/
|
|
8
8
|
Project-URL: Repository, https://github.com/gramaziokohler/compas_timber
|
|
@@ -13,6 +13,9 @@ Classifier: Programming Language :: Python :: 3
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.9
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
19
|
Requires-Python: >=3.9
|
|
17
20
|
Description-Content-Type: text/markdown
|
|
18
21
|
License-File: LICENSE
|
|
@@ -20,9 +23,12 @@ Requires-Dist: rtree
|
|
|
20
23
|
Requires-Dist: compas<3.0,>=2.15.1
|
|
21
24
|
Requires-Dist: compas_model==0.9.2
|
|
22
25
|
Requires-Dist: scipy>=1.1
|
|
26
|
+
Requires-Dist: compas_brep>=0.3.1
|
|
27
|
+
Requires-Dist: compas_pb<2.0,>=1.2.0
|
|
23
28
|
Provides-Extra: dev
|
|
24
29
|
Requires-Dist: bump-my-version; extra == "dev"
|
|
25
30
|
Requires-Dist: compas_invocations2[mkdocs]>=1.0.2; extra == "dev"
|
|
31
|
+
Requires-Dist: mkdocs-panzoom-plugin; extra == "dev"
|
|
26
32
|
Requires-Dist: invoke>=0.14; extra == "dev"
|
|
27
33
|
Requires-Dist: ruff; extra == "dev"
|
|
28
34
|
Requires-Dist: twine; extra == "dev"
|
|
@@ -34,15 +40,19 @@ Requires-Dist: tomlkit; extra == "dev"
|
|
|
34
40
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
35
41
|
Requires-Dist: pytest-randomly; extra == "dev"
|
|
36
42
|
Requires-Dist: pre-commit; extra == "dev"
|
|
43
|
+
Requires-Dist: pyyaml; extra == "dev"
|
|
44
|
+
Requires-Dist: compas_brep[occ]; extra == "dev"
|
|
37
45
|
Provides-Extra: gh
|
|
38
46
|
Requires-Dist: compas_invocations2; extra == "gh"
|
|
39
47
|
Requires-Dist: tomlkit; extra == "gh"
|
|
40
48
|
Requires-Dist: pythonnet; extra == "gh"
|
|
49
|
+
Provides-Extra: viz
|
|
50
|
+
Requires-Dist: compas_brep[occ]; extra == "viz"
|
|
51
|
+
Requires-Dist: compas_viewer; extra == "viz"
|
|
41
52
|
Dynamic: license-file
|
|
42
53
|
|
|
43
54
|
<h1>
|
|
44
|
-
<img src="docs
|
|
45
|
-
COMPAS Timber
|
|
55
|
+
<img src="docs/_logo/PNG_tranparent-background.png" alt="COMPAS Timber logo" width="70" height="70" align="absmiddle"> COMPAS Timber
|
|
46
56
|
</h1>
|
|
47
57
|
|
|
48
58
|
|
|
@@ -52,26 +62,44 @@ Dynamic: license-file
|
|
|
52
62
|
[](https://pypi.python.org/project/compas_timber)
|
|
53
63
|
[](https://pypi.python.org/pypi/compas_timber)
|
|
54
64
|
[](https://pypi.python.org/pypi/compas_timber)
|
|
55
|
-
[](https://doi.org/10.5281/zenodo.7934266)
|
|
56
66
|
[](https://twitter.com/compas_dev)
|
|
57
67
|
[](https://compas.dev/#/)
|
|
58
68
|

|
|
59
69
|
|
|
60
|
-
`compas_timber` is a user-friendly open-source software toolkit
|
|
70
|
+
`compas_timber` is a user-friendly open-source software toolkit that streamlines the design-to-fabrication workflow of timber frame structures. A project is designed and refined in a single digital model that also produces the manufacturing data, so it can go from first concept to fabrication without re-modeling or back-and-forth rework along the way. By lowering the threshold for creating versatile and resource-aware timber designs, we aim to increase the use of timber in architecture.
|
|
61
71
|
|
|
62
72
|
## Installation
|
|
63
73
|
|
|
64
|
-
|
|
74
|
+
We recommend managing environments and dependencies with [uv](https://docs.astral.sh/uv/), but a plain `pip install compas_timber` works just as well.
|
|
75
|
+
|
|
76
|
+
Add `compas_timber` to your project:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
uv add compas_timber
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
To visualize models outside of Rhino, install with the `viz` extra, which adds [compas_viewer](https://github.com/compas-dev/compas_viewer) and `compas_brep[occ]`:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
uv add "compas_timber[viz]"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
For a development setup, clone the repository and sync the environment:
|
|
65
89
|
|
|
66
90
|
```bash
|
|
67
|
-
|
|
91
|
+
git clone https://github.com/gramaziokohler/compas_timber.git
|
|
92
|
+
cd compas_timber
|
|
93
|
+
uv sync --extra dev
|
|
94
|
+
uv run pytest
|
|
68
95
|
```
|
|
69
96
|
|
|
70
97
|
## First Steps
|
|
71
98
|
|
|
72
99
|
* [Documentation](https://gramaziokohler.github.io/compas_timber/)
|
|
73
|
-
* [COMPAS TIMBER Grasshopper
|
|
74
|
-
* [COMPAS TIMBER
|
|
100
|
+
* [COMPAS TIMBER Grasshopper Plugin (timber_design)](https://github.com/gramaziokohler/timber_design)
|
|
101
|
+
* [COMPAS TIMBER Grasshopper Tutorial](https://gramaziokohler.github.io/timber_design/)
|
|
102
|
+
* [COMPAS TIMBER API Reference](https://gramaziokohler.github.io/compas_timber/latest/api/compas_timber.model/)
|
|
75
103
|
|
|
76
104
|
## Questions and feedback
|
|
77
105
|
|
|
@@ -86,9 +114,9 @@ If you found an issue or have a suggestion for a dandy new feature, please file
|
|
|
86
114
|
|
|
87
115
|
We love contributions!
|
|
88
116
|
|
|
89
|
-
Check the [Contributor's Guide](
|
|
117
|
+
Check the [Contributor's Guide](CONTRIBUTING.md)
|
|
90
118
|
for more details.
|
|
91
119
|
|
|
92
120
|
## Credits
|
|
93
121
|
|
|
94
|
-
`compas_timber` is currently developed by Gramazio Kohler Research. See
|
|
122
|
+
`compas_timber` is currently developed by Gramazio Kohler Research. See [`CITATION.cff`](CITATION.cff) for a complete list of authors.
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
<h1>
|
|
2
|
-
<img src="docs
|
|
3
|
-
COMPAS Timber
|
|
2
|
+
<img src="docs/_logo/PNG_tranparent-background.png" alt="COMPAS Timber logo" width="70" height="70" align="absmiddle"> COMPAS Timber
|
|
4
3
|
</h1>
|
|
5
4
|
|
|
6
5
|
|
|
@@ -10,26 +9,44 @@
|
|
|
10
9
|
[](https://pypi.python.org/project/compas_timber)
|
|
11
10
|
[](https://pypi.python.org/pypi/compas_timber)
|
|
12
11
|
[](https://pypi.python.org/pypi/compas_timber)
|
|
13
|
-
[](https://doi.org/10.5281/zenodo.7934266)
|
|
14
13
|
[](https://twitter.com/compas_dev)
|
|
15
14
|
[](https://compas.dev/#/)
|
|
16
15
|

|
|
17
16
|
|
|
18
|
-
`compas_timber` is a user-friendly open-source software toolkit
|
|
17
|
+
`compas_timber` is a user-friendly open-source software toolkit that streamlines the design-to-fabrication workflow of timber frame structures. A project is designed and refined in a single digital model that also produces the manufacturing data, so it can go from first concept to fabrication without re-modeling or back-and-forth rework along the way. By lowering the threshold for creating versatile and resource-aware timber designs, we aim to increase the use of timber in architecture.
|
|
19
18
|
|
|
20
19
|
## Installation
|
|
21
20
|
|
|
22
|
-
|
|
21
|
+
We recommend managing environments and dependencies with [uv](https://docs.astral.sh/uv/), but a plain `pip install compas_timber` works just as well.
|
|
22
|
+
|
|
23
|
+
Add `compas_timber` to your project:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
uv add compas_timber
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
To visualize models outside of Rhino, install with the `viz` extra, which adds [compas_viewer](https://github.com/compas-dev/compas_viewer) and `compas_brep[occ]`:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
uv add "compas_timber[viz]"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
For a development setup, clone the repository and sync the environment:
|
|
23
36
|
|
|
24
37
|
```bash
|
|
25
|
-
|
|
38
|
+
git clone https://github.com/gramaziokohler/compas_timber.git
|
|
39
|
+
cd compas_timber
|
|
40
|
+
uv sync --extra dev
|
|
41
|
+
uv run pytest
|
|
26
42
|
```
|
|
27
43
|
|
|
28
44
|
## First Steps
|
|
29
45
|
|
|
30
46
|
* [Documentation](https://gramaziokohler.github.io/compas_timber/)
|
|
31
|
-
* [COMPAS TIMBER Grasshopper
|
|
32
|
-
* [COMPAS TIMBER
|
|
47
|
+
* [COMPAS TIMBER Grasshopper Plugin (timber_design)](https://github.com/gramaziokohler/timber_design)
|
|
48
|
+
* [COMPAS TIMBER Grasshopper Tutorial](https://gramaziokohler.github.io/timber_design/)
|
|
49
|
+
* [COMPAS TIMBER API Reference](https://gramaziokohler.github.io/compas_timber/latest/api/compas_timber.model/)
|
|
33
50
|
|
|
34
51
|
## Questions and feedback
|
|
35
52
|
|
|
@@ -44,9 +61,9 @@ If you found an issue or have a suggestion for a dandy new feature, please file
|
|
|
44
61
|
|
|
45
62
|
We love contributions!
|
|
46
63
|
|
|
47
|
-
Check the [Contributor's Guide](
|
|
64
|
+
Check the [Contributor's Guide](CONTRIBUTING.md)
|
|
48
65
|
for more details.
|
|
49
66
|
|
|
50
67
|
## Credits
|
|
51
68
|
|
|
52
|
-
`compas_timber` is currently developed by Gramazio Kohler Research. See
|
|
69
|
+
`compas_timber` is currently developed by Gramazio Kohler Research. See [`CITATION.cff`](CITATION.cff) for a complete list of authors.
|
|
@@ -6,20 +6,23 @@
|
|
|
6
6
|
name = "compas_timber"
|
|
7
7
|
description = "COMPAS package for modeling, designing and fabricating timber assemblies."
|
|
8
8
|
authors = [
|
|
9
|
-
{
|
|
10
|
-
{
|
|
11
|
-
{
|
|
12
|
-
{
|
|
13
|
-
{
|
|
14
|
-
{
|
|
15
|
-
{
|
|
16
|
-
{
|
|
17
|
-
{
|
|
18
|
-
{
|
|
19
|
-
{
|
|
20
|
-
{
|
|
21
|
-
{
|
|
22
|
-
{
|
|
9
|
+
{name = "Aleksandra Anna Apolinarska"},
|
|
10
|
+
{name = "Chen Kasirer"},
|
|
11
|
+
{name = "Gonzalo Casas"},
|
|
12
|
+
{name = "Jonas Haldemann"},
|
|
13
|
+
{name = "Oliver Appling Bucklin"},
|
|
14
|
+
{name = "Aurèle L. Gheyselinck"},
|
|
15
|
+
{name = "Panayiotis Papacharalambous"},
|
|
16
|
+
{name = "Anastasiia Stryzhevska"},
|
|
17
|
+
{name = "Jelle Feringa"},
|
|
18
|
+
{name = "Joseph Kenny"},
|
|
19
|
+
{name = "Beverly Lytle"},
|
|
20
|
+
{name = "Eric Gozzi"},
|
|
21
|
+
{name = "Rodrigo Arca Zimmermann"},
|
|
22
|
+
{name = "Nicolas Benjamin Boscoboinik"},
|
|
23
|
+
{name = "Paul Jaeggi"},
|
|
24
|
+
{name = "Matthias Helmreich"},
|
|
25
|
+
{name = "Daniel Nunes Locatelli"},
|
|
23
26
|
]
|
|
24
27
|
license = "MIT"
|
|
25
28
|
readme = "README.md"
|
|
@@ -33,19 +36,25 @@ classifiers = [
|
|
|
33
36
|
"Programming Language :: Python :: 3.9",
|
|
34
37
|
"Programming Language :: Python :: 3.10",
|
|
35
38
|
"Programming Language :: Python :: 3.11",
|
|
39
|
+
"Programming Language :: Python :: 3.12",
|
|
40
|
+
"Programming Language :: Python :: 3.13",
|
|
41
|
+
"Programming Language :: Python :: 3.14",
|
|
36
42
|
]
|
|
37
43
|
|
|
38
44
|
dependencies = [
|
|
39
45
|
"rtree",
|
|
40
46
|
"compas >=2.15.1, <3.0",
|
|
41
47
|
"compas_model == 0.9.2", # pin until first release
|
|
42
|
-
"scipy >= 1.1"
|
|
48
|
+
"scipy >= 1.1",
|
|
49
|
+
"compas_brep >= 0.3.1",
|
|
50
|
+
"compas_pb >= 1.2.0, < 2.0",
|
|
43
51
|
]
|
|
44
52
|
|
|
45
53
|
[project.optional-dependencies]
|
|
46
54
|
dev = [
|
|
47
55
|
"bump-my-version",
|
|
48
56
|
"compas_invocations2[mkdocs]>=1.0.2",
|
|
57
|
+
"mkdocs-panzoom-plugin",
|
|
49
58
|
"invoke >=0.14",
|
|
50
59
|
"ruff",
|
|
51
60
|
"twine",
|
|
@@ -57,6 +66,8 @@ dev = [
|
|
|
57
66
|
"pytest-cov",
|
|
58
67
|
"pytest-randomly",
|
|
59
68
|
"pre-commit",
|
|
69
|
+
"pyyaml",
|
|
70
|
+
"compas_brep[occ]"
|
|
60
71
|
]
|
|
61
72
|
|
|
62
73
|
gh = [
|
|
@@ -65,15 +76,23 @@ gh = [
|
|
|
65
76
|
"pythonnet",
|
|
66
77
|
]
|
|
67
78
|
|
|
79
|
+
viz = [
|
|
80
|
+
"compas_brep[occ]",
|
|
81
|
+
"compas_viewer"
|
|
82
|
+
]
|
|
83
|
+
|
|
68
84
|
[project.urls]
|
|
69
85
|
Homepage = "https://gramaziokohler.github.io/compas_timber/latest/"
|
|
70
86
|
Repository = "https://github.com/gramaziokohler/compas_timber"
|
|
71
87
|
|
|
88
|
+
[project.entry-points.'compas_pb.plugins']
|
|
89
|
+
serializers = 'compas_timber.proto.conversions'
|
|
90
|
+
|
|
72
91
|
# ============================================================================
|
|
73
92
|
# Setup and build
|
|
74
93
|
# ============================================================================
|
|
75
94
|
[build-system]
|
|
76
|
-
requires = ["setuptools>=68", "wheel"]
|
|
95
|
+
requires = ["setuptools>=68", "wheel", "compas_pb >= 1.2.0, < 2.0", "grpcio-tools"]
|
|
77
96
|
build-backend = "setuptools.build_meta"
|
|
78
97
|
|
|
79
98
|
[tool.setuptools]
|
|
@@ -83,42 +102,25 @@ zip-safe = false
|
|
|
83
102
|
|
|
84
103
|
[tool.setuptools.dynamic]
|
|
85
104
|
version = { attr = "compas_timber.__version__" }
|
|
86
|
-
dependencies = { file = "requirements.txt" }
|
|
87
|
-
optional-dependencies = { dev = { file = "requirements-dev.txt" } }
|
|
88
105
|
|
|
89
106
|
[tool.setuptools.packages.find]
|
|
90
107
|
where = ["src"]
|
|
91
108
|
|
|
92
109
|
[tool.setuptools.package-data]
|
|
110
|
+
"compas_timber.fabrication" = ["basic_characters.zip"]
|
|
93
111
|
|
|
94
112
|
# ============================================================================
|
|
95
113
|
# Release
|
|
96
114
|
# ============================================================================
|
|
97
115
|
|
|
116
|
+
# `release-pr` bumps the version and `release-check` validates it; both support
|
|
117
|
+
# stable semantic versions only, and both drive the commit/tag through the
|
|
118
|
+
# release pull request rather than through bump-my-version.
|
|
98
119
|
[tool.bumpversion]
|
|
99
|
-
current_version = "
|
|
120
|
+
current_version = "3.0.0"
|
|
100
121
|
message = "Bump version to {new_version}"
|
|
101
|
-
commit =
|
|
102
|
-
tag =
|
|
103
|
-
parse = """(?x)
|
|
104
|
-
(?P<major>0|[1-9]\\d*)\\.
|
|
105
|
-
(?P<minor>0|[1-9]\\d*)\\.
|
|
106
|
-
(?P<patch>0|[1-9]\\d*)
|
|
107
|
-
(?:
|
|
108
|
-
- # dash separator for pre-release section
|
|
109
|
-
(?P<pre_l>[a-zA-Z-]+) # pre-release label
|
|
110
|
-
(?P<pre_n>0|[1-9]\\d*) # pre-release version number
|
|
111
|
-
)? # pre-release section is optional
|
|
112
|
-
"""
|
|
113
|
-
serialize = [
|
|
114
|
-
"{major}.{minor}.{patch}-{pre_l}{pre_n}",
|
|
115
|
-
"{major}.{minor}.{patch}",
|
|
116
|
-
]
|
|
117
|
-
|
|
118
|
-
[tool.bumpversion.parts.pre_l]
|
|
119
|
-
values = ["dev", "rc", "final"]
|
|
120
|
-
optional_value = "final"
|
|
121
|
-
first_value = "final"
|
|
122
|
+
commit = false
|
|
123
|
+
tag = false
|
|
122
124
|
|
|
123
125
|
[[tool.bumpversion.files]]
|
|
124
126
|
filename = "src/compas_timber/__init__.py"
|
|
@@ -153,6 +155,9 @@ forced_separate = "test_compas_timber"
|
|
|
153
155
|
line-length = 179
|
|
154
156
|
indent-width = 4
|
|
155
157
|
target-version = "py39"
|
|
158
|
+
# protoc-generated modules are not authored by hand and are regenerated by
|
|
159
|
+
# `invoke pre_build`; linting them makes `invoke lint` fail in CI.
|
|
160
|
+
extend-exclude = ["*_pb2.py", "*_pb2.pyi"]
|
|
156
161
|
|
|
157
162
|
[tool.ruff.lint]
|
|
158
163
|
select = ["E", "F", "I"]
|
|
@@ -192,3 +197,6 @@ python_files = [
|
|
|
192
197
|
addopts = "-ra --strict --doctest-modules --doctest-glob=*.rst --tb=short"
|
|
193
198
|
doctest_optionflags= "NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL ALLOW_UNICODE ALLOW_BYTES NUMBER"
|
|
194
199
|
filterwarnings = "ignore::DeprecationWarning"
|
|
200
|
+
markers = [
|
|
201
|
+
"requires_occ: marks tests that need the OCC Brep backend, which is not available on Python 3.9",
|
|
202
|
+
]
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import abc
|
|
2
|
-
from functools import wraps
|
|
3
2
|
|
|
4
3
|
from compas.geometry import Frame
|
|
5
4
|
from compas.geometry import Line
|
|
@@ -7,21 +6,42 @@ from compas.geometry import PlanarSurface
|
|
|
7
6
|
from compas.geometry import Transformation
|
|
8
7
|
from compas.geometry import Vector
|
|
9
8
|
from compas_model.elements import Element
|
|
10
|
-
from compas_model.elements import reset_computed
|
|
11
9
|
|
|
10
|
+
# Cached attributes, in two tiers. Element classes extend these with their own in class attributes of the same name.
|
|
11
|
+
# Element tier: derived from the element's own data (its geometry, features, transformation).
|
|
12
|
+
ELEMENT_CACHE = ("_elementgeometry",)
|
|
13
|
+
# Model tier: derived from the element's placement in the model, i.e. also from its ancestors' transformations.
|
|
14
|
+
MODEL_CACHE = ("_modeltransformation", "_modelgeometry", "_aabb", "_obb", "_collision_mesh", "_point", "_surface_mesh", "_volumetric_mesh")
|
|
12
15
|
|
|
13
|
-
def reset_timber_attrs(f):
|
|
14
|
-
"""Decorator to reset cached timber-specific attributes."""
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
def clear_element_cache(element):
|
|
18
|
+
"""Clear the cached data of `element` after its own data changed (geometry, features, transformation).
|
|
19
|
+
|
|
20
|
+
Its model-space data is derived from it, so this also calls :func:`clear_model_cache`.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
element : :class:`compas_model.elements.Element`
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
for name in getattr(element, "ELEMENT_CACHE", ELEMENT_CACHE):
|
|
28
|
+
setattr(element, name, None)
|
|
29
|
+
clear_model_cache(element)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def clear_model_cache(element):
|
|
33
|
+
"""Clear the cached model-space data of `element` and of all its descendants, after its placement changed.
|
|
34
|
+
|
|
35
|
+
The descendants' placement is composed from `element`'s, so their model-space data is cleared too.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
element : :class:`compas_model.elements.Element`
|
|
23
40
|
|
|
24
|
-
|
|
41
|
+
"""
|
|
42
|
+
for e in [node.element for node in element.treenode.traverse()] if element.treenode else [element]:
|
|
43
|
+
for name in getattr(e, "MODEL_CACHE", MODEL_CACHE):
|
|
44
|
+
setattr(e, name, None)
|
|
25
45
|
|
|
26
46
|
|
|
27
47
|
class TimberElement(Element, abc.ABC):
|
|
@@ -63,10 +83,16 @@ class TimberElement(Element, abc.ABC):
|
|
|
63
83
|
|
|
64
84
|
"""
|
|
65
85
|
|
|
86
|
+
MODEL_CACHE = MODEL_CACHE + ("_blank", "_ref_frame", "_geometry")
|
|
87
|
+
|
|
66
88
|
@property
|
|
67
89
|
def __data__(self):
|
|
68
90
|
data = {}
|
|
69
|
-
|
|
91
|
+
# not `self.frame`: that is `Frame.from_transformation(self.modeltransformation)`, the world-composed
|
|
92
|
+
# frame with the whole ancestor chain baked in. The constructor treats `frame` as `self.transformation`,
|
|
93
|
+
# the *local*, parent-relative placement - so for a nested element (a child of another element in the
|
|
94
|
+
# model tree), storing the world frame would double-apply the ancestor's transformation on deserialization.
|
|
95
|
+
data["frame"] = Frame.from_transformation(self.transformation)
|
|
70
96
|
data["length"] = self.length
|
|
71
97
|
data["width"] = self.width
|
|
72
98
|
data["height"] = self.height
|
|
@@ -85,31 +111,6 @@ class TimberElement(Element, abc.ABC):
|
|
|
85
111
|
self._ref_frame = None
|
|
86
112
|
self.debug_info = []
|
|
87
113
|
|
|
88
|
-
@reset_computed
|
|
89
|
-
@reset_timber_attrs
|
|
90
|
-
def _reset_computed_dummy(self):
|
|
91
|
-
"""Dummy method to trigger reset_computed decorator."""
|
|
92
|
-
pass
|
|
93
|
-
|
|
94
|
-
def reset_computed_properties(self):
|
|
95
|
-
"""Reset all computed/cached properties."""
|
|
96
|
-
self._reset_computed_dummy()
|
|
97
|
-
|
|
98
|
-
def clear_model_dependent_cache(self):
|
|
99
|
-
"""Clear cached attributes that depend on the element's position in the model hierarchy.
|
|
100
|
-
|
|
101
|
-
Preserves model-independent caches such as ``_elementgeometry``, features,
|
|
102
|
-
and blank extensions.
|
|
103
|
-
"""
|
|
104
|
-
self._modeltransformation = None
|
|
105
|
-
self._modelgeometry = None
|
|
106
|
-
self._aabb = None
|
|
107
|
-
self._obb = None
|
|
108
|
-
self._collision_mesh = None
|
|
109
|
-
self._blank = None
|
|
110
|
-
self._ref_frame = None
|
|
111
|
-
self._geometry = None
|
|
112
|
-
|
|
113
114
|
@property
|
|
114
115
|
def is_beam(self):
|
|
115
116
|
return False
|
|
@@ -129,14 +130,15 @@ class TimberElement(Element, abc.ABC):
|
|
|
129
130
|
return self._features
|
|
130
131
|
|
|
131
132
|
@features.setter
|
|
132
|
-
@reset_computed
|
|
133
133
|
def features(self, features):
|
|
134
134
|
self._features = features
|
|
135
|
+
clear_element_cache(self)
|
|
135
136
|
|
|
136
|
-
@
|
|
137
|
-
def
|
|
138
|
-
#
|
|
139
|
-
|
|
137
|
+
@Element.transformation.setter
|
|
138
|
+
def transformation(self, transformation):
|
|
139
|
+
# `Element.transform()` goes through here too
|
|
140
|
+
self._transformation = transformation
|
|
141
|
+
clear_element_cache(self)
|
|
140
142
|
|
|
141
143
|
@property
|
|
142
144
|
def geometry(self):
|
|
@@ -178,25 +180,21 @@ class TimberElement(Element, abc.ABC):
|
|
|
178
180
|
self.remove_blank_extension()
|
|
179
181
|
self.debug_info = []
|
|
180
182
|
|
|
181
|
-
@reset_computed
|
|
182
|
-
@reset_timber_attrs
|
|
183
183
|
def add_feature(self, feature):
|
|
184
184
|
# type: (BTLxProcessing) -> None
|
|
185
|
-
"""Adds
|
|
185
|
+
"""Adds a feature to the element.
|
|
186
186
|
|
|
187
187
|
Parameters
|
|
188
188
|
----------
|
|
189
|
-
feature : :class:`~compas_timber.fabrication.BTLxProcessing`
|
|
189
|
+
feature : :class:`~compas_timber.fabrication.BTLxProcessing`
|
|
190
190
|
The feature to be added.
|
|
191
191
|
|
|
192
192
|
"""
|
|
193
|
-
self.
|
|
193
|
+
self.add_features(feature)
|
|
194
194
|
|
|
195
|
-
@reset_computed
|
|
196
|
-
@reset_timber_attrs
|
|
197
195
|
def add_features(self, features):
|
|
198
196
|
# type: (BTLxProcessing | list[BTLxProcessing]) -> None
|
|
199
|
-
"""Adds one or more features to the
|
|
197
|
+
"""Adds one or more features to the element.
|
|
200
198
|
|
|
201
199
|
Parameters
|
|
202
200
|
----------
|
|
@@ -204,15 +202,14 @@ class TimberElement(Element, abc.ABC):
|
|
|
204
202
|
The feature or features to be added described as a BTLxProcessing or a list of BTLxProcessings.
|
|
205
203
|
|
|
206
204
|
"""
|
|
205
|
+
clear_element_cache(self)
|
|
207
206
|
if not isinstance(features, list):
|
|
208
207
|
features = [features]
|
|
209
208
|
self._features.extend(features) # type: ignore
|
|
210
209
|
|
|
211
|
-
@reset_computed
|
|
212
|
-
@reset_timber_attrs
|
|
213
210
|
def remove_features(self, features=None):
|
|
214
211
|
# type: (None | BTLxProcessing | list[BTLxProcessing]) -> None
|
|
215
|
-
"""Removes
|
|
212
|
+
"""Removes one or more features from the element.
|
|
216
213
|
|
|
217
214
|
Parameters
|
|
218
215
|
----------
|
|
@@ -221,6 +218,7 @@ class TimberElement(Element, abc.ABC):
|
|
|
221
218
|
If None, all features will be removed.
|
|
222
219
|
|
|
223
220
|
"""
|
|
221
|
+
clear_element_cache(self)
|
|
224
222
|
if features is None:
|
|
225
223
|
self._features = []
|
|
226
224
|
else:
|
|
@@ -4,7 +4,6 @@ from .i_simple_scarf import ISimpleScarf
|
|
|
4
4
|
from .l_butt import LButtJoint
|
|
5
5
|
from .l_lap import LLapJoint
|
|
6
6
|
from .l_miter import LMiterJoint
|
|
7
|
-
from .l_miter import MiterPlaneSpec
|
|
8
7
|
from .l_french_ridge_lap import LFrenchRidgeLapJoint
|
|
9
8
|
from .lap_joint import LapJoint
|
|
10
9
|
from .joint_candidate import JointCandidate
|
|
@@ -13,6 +12,7 @@ from .solver import ConnectionSolver
|
|
|
13
12
|
from .solver import PlateConnectionSolver
|
|
14
13
|
from .solver import JointTopology
|
|
15
14
|
from .solver import find_neighboring_elements
|
|
15
|
+
from .candidate_dispatch import get_connection_candidate
|
|
16
16
|
from .t_butt import TButtJoint
|
|
17
17
|
from .t_step_joint import TStepJoint
|
|
18
18
|
from .t_birdsmouth import TBirdsmouthJoint
|
|
@@ -40,8 +40,11 @@ from .plate_miter_joint import PlateMiterJoint
|
|
|
40
40
|
from .panel_butt_joint import PanelLButtJoint
|
|
41
41
|
from .panel_butt_joint import PanelTButtJoint
|
|
42
42
|
from .panel_miter_joint import PanelMiterJoint
|
|
43
|
+
from .panel_layer_butt_joint import PanelLLayerButtJoint
|
|
43
44
|
from .cluster import Cluster
|
|
44
45
|
from .cluster import get_clusters_from_joint_candidates
|
|
46
|
+
from .cluster import get_topology_from_joints
|
|
47
|
+
from .composite_joint import CompositeJoint
|
|
45
48
|
|
|
46
49
|
|
|
47
50
|
__all__ = [
|
|
@@ -66,6 +69,7 @@ __all__ = [
|
|
|
66
69
|
"ConnectionSolver",
|
|
67
70
|
"PlateConnectionSolver",
|
|
68
71
|
"find_neighboring_elements",
|
|
72
|
+
"get_connection_candidate",
|
|
69
73
|
"TDovetailJoint",
|
|
70
74
|
"MortiseTenonJoint",
|
|
71
75
|
"BallNodeJoint",
|
|
@@ -74,7 +78,6 @@ __all__ = [
|
|
|
74
78
|
"YButtJoint",
|
|
75
79
|
"TOliGinaJoint",
|
|
76
80
|
"CutPlaneSpec",
|
|
77
|
-
"MiterPlaneSpec",
|
|
78
81
|
"beam_ref_side_incidence",
|
|
79
82
|
"beam_ref_side_incidence_with_vector",
|
|
80
83
|
"point_centerline_towards_joint",
|
|
@@ -89,6 +92,9 @@ __all__ = [
|
|
|
89
92
|
"PanelLButtJoint",
|
|
90
93
|
"PanelTButtJoint",
|
|
91
94
|
"PanelMiterJoint",
|
|
95
|
+
"PanelLLayerButtJoint",
|
|
92
96
|
"Cluster",
|
|
93
97
|
"get_clusters_from_joint_candidates",
|
|
98
|
+
"get_topology_from_joints",
|
|
99
|
+
"CompositeJoint",
|
|
94
100
|
]
|
|
@@ -131,4 +131,6 @@ class BallNodeJoint(Joint):
|
|
|
131
131
|
pt = beam.centerline.closest_point(self._node_point)
|
|
132
132
|
interface.frame = Frame(pt, Vector.from_start_end(pt, beam.centerline.midpoint), beam.frame.zaxis)
|
|
133
133
|
self.fastener.interfaces.append(interface)
|
|
134
|
-
|
|
134
|
+
features = interface.get_features(beam)
|
|
135
|
+
beam.add_features(features)
|
|
136
|
+
self.features.extend(features)
|