compas-timber 2.0.0.dev0__tar.gz → 2.1.1.dev0__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.0.0.dev0/src/compas_timber.egg-info → compas_timber-2.1.1.dev0}/PKG-INFO +4 -6
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/pyproject.toml +8 -6
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/__init__.py +1 -1
- {compas_timber-2.0.0.dev0/src/compas_timber/connections → compas_timber-2.1.1.dev0/src/compas_timber}/analyzers.py +68 -19
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/base.py +5 -5
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/__init__.py +8 -18
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/joint.py +44 -5
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/joint_candidate.py +2 -2
- compas_timber-2.1.1.dev0/src/compas_timber/connections/l_miter.py +289 -0
- compas_timber-2.1.1.dev0/src/compas_timber/connections/l_tenon_mortise.py +143 -0
- compas_timber-2.0.0.dev0/src/compas_timber/connections/t_tenon_mortise.py → compas_timber-2.1.1.dev0/src/compas_timber/connections/mortise_tenon.py +51 -99
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/oligina.py +40 -6
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/plate_joint.py +13 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/solver.py +4 -6
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/t_dovetail.py +47 -49
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/t_step_joint.py +62 -36
- compas_timber-2.1.1.dev0/src/compas_timber/connections/t_tenon_mortise.py +109 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/y_butt.py +4 -2
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/elements/beam.py +29 -5
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/elements/fastener.py +5 -5
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/elements/fasteners/ball_node_fastener.py +9 -4
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/elements/fasteners/plate_fastener.py +14 -11
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/elements/features.py +2 -2
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/elements/panel.py +4 -13
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/elements/plate.py +3 -3
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/elements/plate_geometry.py +20 -10
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/errors.py +1 -1
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/btlx.py +118 -18
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/double_cut.py +9 -40
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/dovetail_mortise.py +18 -49
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/dovetail_tenon.py +26 -50
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/drilling.py +11 -25
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/free_contour.py +67 -36
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/french_ridge_lap.py +8 -38
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/jack_cut.py +8 -38
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/lap.py +16 -52
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/longitudinal_cut.py +13 -56
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/mortise.py +15 -50
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/pocket.py +29 -65
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/slot.py +15 -47
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/step_joint.py +11 -42
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/step_joint_notch.py +15 -46
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/tenon.py +17 -48
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/text.py +14 -27
- compas_timber-2.1.1.dev0/src/compas_timber/geometry.py +62 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/model.py +95 -44
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/rhino/__init__.py +2 -2
- compas_timber-2.1.1.dev0/src/compas_timber/structural.py +267 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0/src/compas_timber.egg-info}/PKG-INFO +4 -6
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber.egg-info/SOURCES.txt +4 -1
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber.egg-info/requires.txt +2 -4
- compas_timber-2.0.0.dev0/src/compas_timber/connections/l_miter.py +0 -181
- compas_timber-2.0.0.dev0/src/compas_timber/structural.py +0 -115
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/LICENSE +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/README.md +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/setup.cfg +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/ball_node.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/butt_joint.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/l_butt.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/l_french_ridge_lap.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/l_lap.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/lap_joint.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/panel_butt_joint.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/panel_joint.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/panel_miter_joint.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/plate_butt_joint.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/plate_miter_joint.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/t_birdsmouth.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/t_butt.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/t_lap.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/utilities.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/x_lap.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/x_notch.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/elements/__init__.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/elements/fasteners/__init__.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/fabrication/__init__.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/panel_features/__init__.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/panel_features/panel_connection_interface.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/panel_features/panel_features.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/planning/__init__.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/planning/nesting.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/planning/sequencer.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/rhino/install.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/utils/__init__.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/utils/r_tree.py +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber.egg-info/dependency_links.txt +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber.egg-info/not-zip-safe +0 -0
- {compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/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: 2.
|
|
3
|
+
Version: 2.1.1.dev0
|
|
4
4
|
Summary: COMPAS package for modeling, designing and fabricating timber assemblies.
|
|
5
|
-
Author-email: Aleksandra Anna Apolinarska <apolinarska@arch.ethz.ch>, Chen Kasirer <kasirer@arch.ethz.ch>, Gonzalo Casas <casas@arch.ethz.ch>, Jonas Haldemann <haldemann@arch.ethz.ch>, Oliver Appling Bucklin <bucklin@arch.ethz.ch>, "Aurèle L. Gheyselinck" <gheyselinck@arch.ethz.ch>, Panayiotis Papacharalambous <papacharalambous@arch.ethz.ch>, Anastasiia Stryzhevska <astryzhevska@arch.ethz.ch>, Jelle Feringa <jelleferinga@gmail.com>, Joseph Kenny <jk6372@princeton.edu>, Beverly Lytle <lytle@arch.ethz.ch>, Eric Gozzi <eric.gozzi@arch.ethz.ch>, Rodrigo Arca Zimmermann <rodrigo.arca@gmail.com>
|
|
5
|
+
Author-email: Aleksandra Anna Apolinarska <apolinarska@arch.ethz.ch>, Chen Kasirer <kasirer@arch.ethz.ch>, Gonzalo Casas <casas@arch.ethz.ch>, Jonas Haldemann <haldemann@arch.ethz.ch>, Oliver Appling Bucklin <bucklin@arch.ethz.ch>, "Aurèle L. Gheyselinck" <gheyselinck@arch.ethz.ch>, Panayiotis Papacharalambous <papacharalambous@arch.ethz.ch>, Anastasiia Stryzhevska <astryzhevska@arch.ethz.ch>, Jelle Feringa <jelleferinga@gmail.com>, Joseph Kenny <jk6372@princeton.edu>, Beverly Lytle <lytle@arch.ethz.ch>, Eric Gozzi <eric.gozzi@arch.ethz.ch>, Rodrigo Arca Zimmermann <rodrigo.arca@gmail.com>, Nicolas Benjamin Boscoboinik <boscoboinik@arch.ethz.ch>
|
|
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
|
|
@@ -19,20 +19,18 @@ License-File: LICENSE
|
|
|
19
19
|
Requires-Dist: rtree
|
|
20
20
|
Requires-Dist: compas<3.0,>=2.0
|
|
21
21
|
Requires-Dist: compas_model==0.9.1
|
|
22
|
+
Requires-Dist: scipy>=1.1
|
|
22
23
|
Provides-Extra: dev
|
|
23
24
|
Requires-Dist: bump-my-version; extra == "dev"
|
|
24
|
-
Requires-Dist: compas_invocations2; extra == "dev"
|
|
25
|
+
Requires-Dist: compas_invocations2[mkdocs]>=1.0.2; extra == "dev"
|
|
25
26
|
Requires-Dist: invoke>=0.14; extra == "dev"
|
|
26
27
|
Requires-Dist: ruff; extra == "dev"
|
|
27
|
-
Requires-Dist: sphinx_compas2_theme; extra == "dev"
|
|
28
|
-
Requires-Dist: sphinxcontrib-mermaid; extra == "dev"
|
|
29
28
|
Requires-Dist: twine; extra == "dev"
|
|
30
29
|
Requires-Dist: wheel; extra == "dev"
|
|
31
30
|
Requires-Dist: pytest-mock; extra == "dev"
|
|
32
31
|
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
33
32
|
Requires-Dist: build; extra == "dev"
|
|
34
33
|
Requires-Dist: tomlkit; extra == "dev"
|
|
35
|
-
Requires-Dist: compas_viewer; extra == "dev"
|
|
36
34
|
Requires-Dist: pytest-cov; extra == "dev"
|
|
37
35
|
Requires-Dist: pytest-randomly; extra == "dev"
|
|
38
36
|
Requires-Dist: pre-commit; extra == "dev"
|
|
@@ -18,7 +18,8 @@ authors = [
|
|
|
18
18
|
{ name = "Joseph Kenny", email = "jk6372@princeton.edu" },
|
|
19
19
|
{ name = "Beverly Lytle", email = "lytle@arch.ethz.ch" },
|
|
20
20
|
{ name = "Eric Gozzi", email = "eric.gozzi@arch.ethz.ch" },
|
|
21
|
-
{ name = "Rodrigo Arca Zimmermann", email = "rodrigo.arca@gmail.com" }
|
|
21
|
+
{ name = "Rodrigo Arca Zimmermann", email = "rodrigo.arca@gmail.com" },
|
|
22
|
+
{ name = "Nicolas Benjamin Boscoboinik", email = "boscoboinik@arch.ethz.ch" }
|
|
22
23
|
]
|
|
23
24
|
license = "MIT"
|
|
24
25
|
readme = "README.md"
|
|
@@ -38,23 +39,21 @@ dependencies = [
|
|
|
38
39
|
"rtree",
|
|
39
40
|
"compas >=2.0, <3.0",
|
|
40
41
|
"compas_model == 0.9.1", # pin until first release
|
|
42
|
+
"scipy >= 1.1"
|
|
41
43
|
]
|
|
42
44
|
|
|
43
45
|
[project.optional-dependencies]
|
|
44
46
|
dev = [
|
|
45
47
|
"bump-my-version",
|
|
46
|
-
"compas_invocations2",
|
|
48
|
+
"compas_invocations2[mkdocs]>=1.0.2",
|
|
47
49
|
"invoke >=0.14",
|
|
48
50
|
"ruff",
|
|
49
|
-
"sphinx_compas2_theme",
|
|
50
|
-
"sphinxcontrib-mermaid",
|
|
51
51
|
"twine",
|
|
52
52
|
"wheel",
|
|
53
53
|
"pytest-mock",
|
|
54
54
|
"pytest>=8.0",
|
|
55
55
|
"build",
|
|
56
56
|
"tomlkit",
|
|
57
|
-
"compas_viewer",
|
|
58
57
|
"pytest-cov",
|
|
59
58
|
"pytest-randomly",
|
|
60
59
|
"pre-commit",
|
|
@@ -73,6 +72,9 @@ Repository = "https://github.com/gramaziokohler/compas_timber"
|
|
|
73
72
|
# ============================================================================
|
|
74
73
|
# Setup and build
|
|
75
74
|
# ============================================================================
|
|
75
|
+
[build-system]
|
|
76
|
+
requires = ["setuptools>=68", "wheel"]
|
|
77
|
+
build-backend = "setuptools.build_meta"
|
|
76
78
|
|
|
77
79
|
[tool.setuptools]
|
|
78
80
|
package-dir = { "" = "src" }
|
|
@@ -94,7 +96,7 @@ where = ["src"]
|
|
|
94
96
|
# ============================================================================
|
|
95
97
|
|
|
96
98
|
[tool.bumpversion]
|
|
97
|
-
current_version = "2.
|
|
99
|
+
current_version = "2.1.1-dev0"
|
|
98
100
|
message = "Bump version to {new_version}"
|
|
99
101
|
commit = true
|
|
100
102
|
tag = true
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import math
|
|
4
|
+
from weakref import WeakKeyDictionary
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
import compas.tolerance # noqa: F401
|
|
5
|
-
import compas_model.elements # noqa: F401
|
|
6
|
-
from compas.geometry import KDTree
|
|
6
|
+
from compas.geometry import Point
|
|
7
7
|
from compas.tolerance import TOL
|
|
8
|
+
from compas_model.elements import Element
|
|
8
9
|
|
|
9
|
-
import compas_timber.connections # noqa: F401
|
|
10
|
-
import compas_timber.elements # noqa: F401
|
|
11
10
|
from compas_timber.connections import JointTopology
|
|
11
|
+
from compas_timber.geometry import KDTree
|
|
12
|
+
from compas_timber.model import TimberModel
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class Cluster(object):
|
|
@@ -40,8 +41,7 @@ class Cluster(object):
|
|
|
40
41
|
return len(self.elements)
|
|
41
42
|
|
|
42
43
|
@property
|
|
43
|
-
def elements(self):
|
|
44
|
-
# type: () -> set[compas_model.elements.Element]
|
|
44
|
+
def elements(self) -> set[Element]:
|
|
45
45
|
if not self._elements:
|
|
46
46
|
self._elements = set()
|
|
47
47
|
for joint in self.joints:
|
|
@@ -49,8 +49,7 @@ class Cluster(object):
|
|
|
49
49
|
return self._elements
|
|
50
50
|
|
|
51
51
|
@property
|
|
52
|
-
def location(self):
|
|
53
|
-
# type: () -> compas.geometry.Point
|
|
52
|
+
def location(self) -> Point:
|
|
54
53
|
return self.joints[0].location
|
|
55
54
|
|
|
56
55
|
@property
|
|
@@ -81,6 +80,57 @@ class BeamGroupAnalyzer(object):
|
|
|
81
80
|
raise NotImplementedError
|
|
82
81
|
|
|
83
82
|
|
|
83
|
+
class _CacheEntry(object):
|
|
84
|
+
def __init__(self, fingerprint: frozenset, joints: list, tree: KDTree) -> None:
|
|
85
|
+
self.fingerprint = fingerprint
|
|
86
|
+
self.joints = joints
|
|
87
|
+
self.tree = tree
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class _KDTreeCache(object):
|
|
91
|
+
"""Caches a :class:`KDTree` per model instance, rebuilding it when the joint set changes.
|
|
92
|
+
|
|
93
|
+
The cache is keyed by model identity (via a :class:`~weakref.WeakKeyDictionary`) so the
|
|
94
|
+
tree is automatically released when the model is garbage-collected. A fingerprint of
|
|
95
|
+
the current joint-candidate identities detects structural changes: if joints have been
|
|
96
|
+
added or removed since the tree was built, the tree is transparently rebuilt.
|
|
97
|
+
|
|
98
|
+
Crucially, the cache also stores the *canonical ordering* of joints used when the tree
|
|
99
|
+
was first built. Every caller receives that same list so that KDTree indices are always
|
|
100
|
+
consistent with ``self._joints``, regardless of the iteration order of the underlying set.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
_store = WeakKeyDictionary() # type: WeakKeyDictionary # model -> _CacheEntry
|
|
104
|
+
|
|
105
|
+
@classmethod
|
|
106
|
+
def get(cls, model: TimberModel, joints: list) -> tuple[list, KDTree]:
|
|
107
|
+
"""Return the canonical joints list and :class:`KDTree` for *model*.
|
|
108
|
+
|
|
109
|
+
If the joint set has changed since the last call (joints added or removed),
|
|
110
|
+
a new tree is built and the canonical list is updated.
|
|
111
|
+
|
|
112
|
+
Parameters
|
|
113
|
+
----------
|
|
114
|
+
model : :class:`~compas_timber.model.TimberModel`
|
|
115
|
+
The model whose joint candidates the tree covers.
|
|
116
|
+
joints : list
|
|
117
|
+
The current joint candidates used only to compute the fingerprint and,
|
|
118
|
+
on a cache miss, to build the new tree.
|
|
119
|
+
|
|
120
|
+
Returns
|
|
121
|
+
-------
|
|
122
|
+
tuple[list, :class:`KDTree`]
|
|
123
|
+
``(canonical_joints, tree)`` – the ordering and tree that all callers
|
|
124
|
+
for this model generation must share.
|
|
125
|
+
"""
|
|
126
|
+
fingerprint = frozenset(id(j) for j in joints)
|
|
127
|
+
cached = cls._store.get(model)
|
|
128
|
+
if cached is None or cached.fingerprint != fingerprint:
|
|
129
|
+
cls._store[model] = _CacheEntry(fingerprint, joints, KDTree([j.location for j in joints]))
|
|
130
|
+
entry = cls._store[model]
|
|
131
|
+
return entry.joints, entry.tree
|
|
132
|
+
|
|
133
|
+
|
|
84
134
|
class NBeamKDTreeAnalyzer(BeamGroupAnalyzer):
|
|
85
135
|
"""Finds clusters of N beams connected pairwise at the same point within a given max_distance.
|
|
86
136
|
|
|
@@ -96,14 +146,13 @@ class NBeamKDTreeAnalyzer(BeamGroupAnalyzer):
|
|
|
96
146
|
|
|
97
147
|
def __init__(self, model, n=2, max_distance=None):
|
|
98
148
|
super(NBeamKDTreeAnalyzer, self).__init__()
|
|
99
|
-
|
|
100
|
-
if not
|
|
149
|
+
joints = list(model.joint_candidates)
|
|
150
|
+
if not joints:
|
|
101
151
|
raise ValueError("The model has no joint candidates to analyze. Forgot to call `model.connect_adjacent_beams()`?")
|
|
102
152
|
|
|
103
|
-
self._kdtree =
|
|
153
|
+
self._joints, self._kdtree = _KDTreeCache.get(model, joints)
|
|
104
154
|
self._n = n
|
|
105
155
|
self.max_distance = max_distance or TOL.absolute
|
|
106
|
-
|
|
107
156
|
# TODO: add parameter to specify groupwise clustering, i.e only look at joints of elements within the same group
|
|
108
157
|
|
|
109
158
|
def find(self, exclude=None):
|
|
@@ -231,14 +280,14 @@ def MaxNCompositeAnalyzer(model, n, max_distance=None):
|
|
|
231
280
|
The TimberModel to analyze.
|
|
232
281
|
n : int
|
|
233
282
|
The maximum cluster size.
|
|
234
|
-
|
|
235
|
-
The
|
|
283
|
+
max_distance : float | None
|
|
284
|
+
The max distance to use for the analysis. If None, a default max distance is used.
|
|
236
285
|
|
|
237
286
|
Returns
|
|
238
287
|
-------
|
|
239
288
|
CompositeAnalyzer
|
|
240
289
|
An instance of CompositeAnalyzer that finds clusters of size n down to 2.
|
|
241
290
|
"""
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return CompositeAnalyzer([
|
|
291
|
+
# All analyzers share the same KDTree automatically via the class-level cache keyed on model
|
|
292
|
+
max_cluster_size = max(n, 2)
|
|
293
|
+
return CompositeAnalyzer([NBeamKDTreeAnalyzer(model, n=k, max_distance=max_distance) for k in range(max_cluster_size, 1, -1)])
|
|
@@ -201,7 +201,7 @@ class TimberElement(Element, abc.ABC):
|
|
|
201
201
|
|
|
202
202
|
Parameters
|
|
203
203
|
----------
|
|
204
|
-
|
|
204
|
+
features : :class:`~compas_timber.fabrication.BTLxProcessing` | list(:class:`~compas_timber.fabrication.BTLxProcessing`) | None
|
|
205
205
|
The feature or features to be removed described as a BTLxProcessing or a list of BTLxProcessings.
|
|
206
206
|
If None, all features will be removed.
|
|
207
207
|
|
|
@@ -351,7 +351,7 @@ class TimberElement(Element, abc.ABC):
|
|
|
351
351
|
|
|
352
352
|
def get_dimensions_relative_to_side(self, ref_side_index):
|
|
353
353
|
# type: (int) -> tuple[float, float]
|
|
354
|
-
"""Returns the
|
|
354
|
+
"""Returns the dimensions of a timber element with respect to the Y- axis and Normal of the given reference side.
|
|
355
355
|
|
|
356
356
|
Parameters
|
|
357
357
|
----------
|
|
@@ -361,9 +361,9 @@ class TimberElement(Element, abc.ABC):
|
|
|
361
361
|
Returns
|
|
362
362
|
-------
|
|
363
363
|
tuple(float, float)
|
|
364
|
-
|
|
365
|
-
-
|
|
366
|
-
-
|
|
364
|
+
Y-axis dimension, Normal direction dimension.
|
|
365
|
+
- Y-axis dimension: The element dimension along y-axis of reference side.
|
|
366
|
+
- Normal dimension: The element dimension normal to the reference side.
|
|
367
367
|
"""
|
|
368
368
|
if ref_side_index in [1, 3]:
|
|
369
369
|
return self.height, self.width
|
{compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/__init__.py
RENAMED
|
@@ -18,10 +18,12 @@ from .t_lap import TLapJoint
|
|
|
18
18
|
from .x_lap import XLapJoint
|
|
19
19
|
from .x_notch import XNotchJoint
|
|
20
20
|
from .t_dovetail import TDovetailJoint
|
|
21
|
-
from .
|
|
21
|
+
from .mortise_tenon import MortiseTenonJoint
|
|
22
|
+
from .t_tenon_mortise import TTenonMortiseJoint
|
|
23
|
+
from .l_tenon_mortise import LTenonMortiseJoint
|
|
22
24
|
from .ball_node import BallNodeJoint
|
|
23
25
|
from .y_butt import YButtJoint
|
|
24
|
-
from .oligina import
|
|
26
|
+
from .oligina import TOliGinaJoint
|
|
25
27
|
from .utilities import beam_ref_side_incidence
|
|
26
28
|
from .utilities import beam_ref_side_incidence_with_vector
|
|
27
29
|
from .utilities import point_centerline_towards_joint
|
|
@@ -34,13 +36,6 @@ from .plate_miter_joint import PlateMiterJoint
|
|
|
34
36
|
from .panel_butt_joint import PanelLButtJoint
|
|
35
37
|
from .panel_butt_joint import PanelTButtJoint
|
|
36
38
|
from .panel_miter_joint import PanelMiterJoint
|
|
37
|
-
from .analyzers import NBeamKDTreeAnalyzer
|
|
38
|
-
from .analyzers import TripletAnalyzer
|
|
39
|
-
from .analyzers import QuadAnalyzer
|
|
40
|
-
from .analyzers import CompositeAnalyzer
|
|
41
|
-
from .analyzers import Cluster
|
|
42
|
-
from .analyzers import BeamGroupAnalyzer
|
|
43
|
-
from .analyzers import MaxNCompositeAnalyzer
|
|
44
39
|
|
|
45
40
|
__all__ = [
|
|
46
41
|
"Joint",
|
|
@@ -64,10 +59,12 @@ __all__ = [
|
|
|
64
59
|
"PlateConnectionSolver",
|
|
65
60
|
"find_neighboring_elements",
|
|
66
61
|
"TDovetailJoint",
|
|
62
|
+
"MortiseTenonJoint",
|
|
67
63
|
"BallNodeJoint",
|
|
68
|
-
"
|
|
64
|
+
"TTenonMortiseJoint",
|
|
65
|
+
"LTenonMortiseJoint",
|
|
69
66
|
"YButtJoint",
|
|
70
|
-
"
|
|
67
|
+
"TOliGinaJoint",
|
|
71
68
|
"beam_ref_side_incidence",
|
|
72
69
|
"beam_ref_side_incidence_with_vector",
|
|
73
70
|
"point_centerline_towards_joint",
|
|
@@ -80,11 +77,4 @@ __all__ = [
|
|
|
80
77
|
"PanelLButtJoint",
|
|
81
78
|
"PanelTButtJoint",
|
|
82
79
|
"PanelMiterJoint",
|
|
83
|
-
"NBeamKDTreeAnalyzer",
|
|
84
|
-
"TripletAnalyzer",
|
|
85
|
-
"QuadAnalyzer",
|
|
86
|
-
"CompositeAnalyzer",
|
|
87
|
-
"Cluster",
|
|
88
|
-
"BeamGroupAnalyzer",
|
|
89
|
-
"MaxNCompositeAnalyzer",
|
|
90
80
|
]
|
{compas_timber-2.0.0.dev0 → compas_timber-2.1.1.dev0}/src/compas_timber/connections/joint.py
RENAMED
|
@@ -3,12 +3,43 @@ from itertools import combinations
|
|
|
3
3
|
from compas.data import Data
|
|
4
4
|
from compas.geometry import Point
|
|
5
5
|
from compas.geometry import distance_point_line
|
|
6
|
+
from compas.tolerance import TOL
|
|
6
7
|
|
|
7
8
|
from compas_timber.errors import BeamJoiningError
|
|
9
|
+
from compas_timber.utils import distance_segment_segment_points
|
|
8
10
|
|
|
9
11
|
from .solver import JointTopology
|
|
10
12
|
|
|
11
13
|
|
|
14
|
+
def location_from_centerlines(beams):
|
|
15
|
+
"""Compute the approximate joint location from two beam centerlines.
|
|
16
|
+
|
|
17
|
+
Returns the closest point between the two centerlines, or the midpoint
|
|
18
|
+
between them when the beams are skew (non-intersecting).
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
beams : list(:class:`~compas_timber.elements.Beam`)
|
|
23
|
+
A list of two beams for which to calculate the joint location.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
:class:`~compas.geometry.Point`
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
if len(beams) != 2:
|
|
31
|
+
raise ValueError(
|
|
32
|
+
"Automatic location calculation only works for joints connecting 2 elements. "
|
|
33
|
+
"Please set the location manually or implement a custom location calculation for your joint type."
|
|
34
|
+
)
|
|
35
|
+
beam_a, beam_b = beams
|
|
36
|
+
distance, point_a, point_b = distance_segment_segment_points(beam_a.centerline, beam_b.centerline)
|
|
37
|
+
point_a, point_b = Point(*point_a), Point(*point_b)
|
|
38
|
+
if not TOL.is_zero(distance):
|
|
39
|
+
return (point_a + point_b) / 2.0
|
|
40
|
+
return point_a
|
|
41
|
+
|
|
42
|
+
|
|
12
43
|
class Joint(Data):
|
|
13
44
|
"""Base class for a joint connecting two beams.
|
|
14
45
|
|
|
@@ -48,13 +79,16 @@ class Joint(Data):
|
|
|
48
79
|
|
|
49
80
|
def __init__(self, topology=None, location=None, name=None, **kwargs):
|
|
50
81
|
super().__init__(name=name)
|
|
51
|
-
self._topology =
|
|
52
|
-
self._location =
|
|
82
|
+
self._topology = None
|
|
83
|
+
self._location = None
|
|
84
|
+
self.topology = topology
|
|
85
|
+
if location:
|
|
86
|
+
self.location = location
|
|
53
87
|
|
|
54
88
|
@property
|
|
55
89
|
def __data__(self):
|
|
56
90
|
# type: () -> dict
|
|
57
|
-
return {"name": self.name}
|
|
91
|
+
return {"name": self.name, "topology": self.topology, "location": self._location}
|
|
58
92
|
|
|
59
93
|
def __repr__(self):
|
|
60
94
|
return '{}(name="{}")'.format(self.__class__.__name__, self.name)
|
|
@@ -65,11 +99,16 @@ class Joint(Data):
|
|
|
65
99
|
|
|
66
100
|
@topology.setter
|
|
67
101
|
def topology(self, value):
|
|
68
|
-
|
|
69
|
-
self._topology = value
|
|
102
|
+
self._topology = value or JointTopology.TOPO_UNKNOWN
|
|
70
103
|
|
|
71
104
|
@property
|
|
72
105
|
def location(self):
|
|
106
|
+
if self._location is None and all(self.elements):
|
|
107
|
+
self._location = location_from_centerlines(self.elements)
|
|
108
|
+
|
|
109
|
+
if self._location is None:
|
|
110
|
+
raise ValueError("Location of the joint could not be determined. Please set it manually.")
|
|
111
|
+
|
|
73
112
|
return self._location
|
|
74
113
|
|
|
75
114
|
@location.setter
|
|
@@ -5,7 +5,7 @@ from .plate_joint import PlateJoint
|
|
|
5
5
|
class JointCandidate(Joint):
|
|
6
6
|
"""A JointCandidate is an information-only joint, which does not add any features to the elements it connects.
|
|
7
7
|
|
|
8
|
-
It is used to create a first-pass joinery information which can be later used to perform analysis using :class:`~compas_timber.
|
|
8
|
+
It is used to create a first-pass joinery information which can be later used to perform analysis using :class:`~compas_timber.analyzers.BeamGroupAnalyzer`.
|
|
9
9
|
|
|
10
10
|
Please use `JointCandidate.create()` to properly create an instance of this class and associate it with an model.
|
|
11
11
|
|
|
@@ -70,7 +70,7 @@ class JointCandidate(Joint):
|
|
|
70
70
|
class PlateJointCandidate(PlateJoint, JointCandidate):
|
|
71
71
|
"""A PlateJointCandidate is an information-only joint for plate connections.
|
|
72
72
|
|
|
73
|
-
It is used to create a first-pass joinery information which can be later used to perform analysis using :class:`~compas_timber.
|
|
73
|
+
It is used to create a first-pass joinery information which can be later used to perform analysis using :class:`~compas_timber.analyzers.BeamGroupAnalyzer`.
|
|
74
74
|
|
|
75
75
|
Parameters
|
|
76
76
|
----------
|