DeepSDFStruct 1.7.2__py3-none-any.whl

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.
Files changed (165) hide show
  1. DeepSDFStruct/SDF.py +1734 -0
  2. DeepSDFStruct/__init__.py +66 -0
  3. DeepSDFStruct/deep_sdf/__init__.py +69 -0
  4. DeepSDFStruct/deep_sdf/create_screenshots_from_plyfiles.py +65 -0
  5. DeepSDFStruct/deep_sdf/data.py +258 -0
  6. DeepSDFStruct/deep_sdf/metrics/__init__.py +14 -0
  7. DeepSDFStruct/deep_sdf/metrics/mesh_to_analytical.py +24 -0
  8. DeepSDFStruct/deep_sdf/models.py +197 -0
  9. DeepSDFStruct/deep_sdf/networks/__init__.py +8 -0
  10. DeepSDFStruct/deep_sdf/networks/analytic_round_cross.py +105 -0
  11. DeepSDFStruct/deep_sdf/networks/deep_sdf_decoder.py +155 -0
  12. DeepSDFStruct/deep_sdf/networks/hierarchical_deep_sdf_decoder.py +139 -0
  13. DeepSDFStruct/deep_sdf/networks/hierarchical_positional_sdf_decoder.py +190 -0
  14. DeepSDFStruct/deep_sdf/networks/resnet_positional_sdf_decoder.py +108 -0
  15. DeepSDFStruct/deep_sdf/nn_utils.py +70 -0
  16. DeepSDFStruct/deep_sdf/plotting.py +143 -0
  17. DeepSDFStruct/deep_sdf/reconstruction.py +165 -0
  18. DeepSDFStruct/deep_sdf/training.py +840 -0
  19. DeepSDFStruct/deep_sdf/workspace.py +363 -0
  20. DeepSDFStruct/design_of_experiments.py +235 -0
  21. DeepSDFStruct/flexicubes/__init__.py +15 -0
  22. DeepSDFStruct/flexicubes/flexicubes.py +1005 -0
  23. DeepSDFStruct/flexicubes/tables.py +2338 -0
  24. DeepSDFStruct/flexisquares/__init__.py +15 -0
  25. DeepSDFStruct/flexisquares/flexisquares.py +967 -0
  26. DeepSDFStruct/flexisquares/tables.py +63 -0
  27. DeepSDFStruct/lattice_structure.py +254 -0
  28. DeepSDFStruct/local_shapes.py +226 -0
  29. DeepSDFStruct/mesh.py +1184 -0
  30. DeepSDFStruct/optimization.py +357 -0
  31. DeepSDFStruct/parametrization.py +215 -0
  32. DeepSDFStruct/pretrained_models.py +128 -0
  33. DeepSDFStruct/sampling.py +670 -0
  34. DeepSDFStruct/sdf_operations.py +990 -0
  35. DeepSDFStruct/sdf_primitives.py +1416 -0
  36. DeepSDFStruct/splinepy_unitcells/__init__.py +35 -0
  37. DeepSDFStruct/splinepy_unitcells/chi_3D.py +1617 -0
  38. DeepSDFStruct/splinepy_unitcells/cross_lattice.py +165 -0
  39. DeepSDFStruct/splinepy_unitcells/double_lattice_extruded.py +298 -0
  40. DeepSDFStruct/splinepy_unitcells/snappy_3d.py +544 -0
  41. DeepSDFStruct/torch_spline.py +446 -0
  42. DeepSDFStruct/trained_models/analytic_round_cross/LatentCodes/latest.pth +0 -0
  43. DeepSDFStruct/trained_models/analytic_round_cross/ModelParameters/latest.pth +0 -0
  44. DeepSDFStruct/trained_models/analytic_round_cross/OptimizerParameters/latest.pth +0 -0
  45. DeepSDFStruct/trained_models/analytic_round_cross/specs.json +45 -0
  46. DeepSDFStruct/trained_models/chi_and_cross/LatentCodes/latest.pth +0 -0
  47. DeepSDFStruct/trained_models/chi_and_cross/Logs.pth +0 -0
  48. DeepSDFStruct/trained_models/chi_and_cross/ModelParameters/latest.pth +0 -0
  49. DeepSDFStruct/trained_models/chi_and_cross/OptimizerParameters/latest.pth +0 -0
  50. DeepSDFStruct/trained_models/chi_and_cross/specs.json +76 -0
  51. DeepSDFStruct/trained_models/primitives/LatentCodes/latest.pth +0 -0
  52. DeepSDFStruct/trained_models/primitives/ModelParameters/latest.pth +0 -0
  53. DeepSDFStruct/trained_models/primitives/OptimizerParameters/latest.pth +0 -0
  54. DeepSDFStruct/trained_models/primitives/specs.json +46 -0
  55. DeepSDFStruct/trained_models/primitives_2d/LatentCodes/latest.pth +0 -0
  56. DeepSDFStruct/trained_models/primitives_2d/ModelParameters/latest.pth +0 -0
  57. DeepSDFStruct/trained_models/primitives_2d/OptimizerParameters/latest.pth +0 -0
  58. DeepSDFStruct/trained_models/primitives_2d/specs.json +46 -0
  59. DeepSDFStruct/trained_models/round_cross/LatentCodes/latest.pth +0 -0
  60. DeepSDFStruct/trained_models/round_cross/Logs.pth +0 -0
  61. DeepSDFStruct/trained_models/round_cross/ModelParameters/latest.pth +0 -0
  62. DeepSDFStruct/trained_models/round_cross/OptimizerParameters/latest.pth +0 -0
  63. DeepSDFStruct/trained_models/round_cross/specs.json +45 -0
  64. DeepSDFStruct/trained_models/test_experiment/LatentCodes/latent_code_data_map.json +106 -0
  65. DeepSDFStruct/trained_models/test_experiment/specs.json +45 -0
  66. DeepSDFStruct/trained_models/test_experiment/training_summary.json +10 -0
  67. DeepSDFStruct/trained_models/test_experiment_hierarchical/LatentCodes/latent_code_data_map.json +106 -0
  68. DeepSDFStruct/trained_models/test_experiment_hierarchical/specs.json +45 -0
  69. DeepSDFStruct/trained_models/test_experiment_hierarchical/training_summary.json +10 -0
  70. DeepSDFStruct/trained_models/test_experiment_homogenization/LatentCodes/latent_code_data_map.json +5006 -0
  71. DeepSDFStruct/trained_models/test_experiment_homogenization/LatentCodes/latest.pth +0 -0
  72. DeepSDFStruct/trained_models/test_experiment_homogenization/Logs.png +0 -0
  73. DeepSDFStruct/trained_models/test_experiment_homogenization/ModelParameters/latest.pth +0 -0
  74. DeepSDFStruct/trained_models/test_experiment_homogenization/OptimizerParameters/latest.pth +0 -0
  75. DeepSDFStruct/trained_models/test_experiment_homogenization/specs.json +83 -0
  76. DeepSDFStruct/trained_models/test_experiment_homogenization/training_summary.json +10 -0
  77. DeepSDFStruct/utils.py +96 -0
  78. DeepSDFStruct/visualization/latent_viewer.py +211 -0
  79. DeepSDFStruct/visualization/latent_viewer_cli.py +8 -0
  80. benchmarks/generate_sdf_showcase.py +622 -0
  81. benchmarks/sdf_from_mesh_benchmark.py +52 -0
  82. benchmarks/sdf_from_mesh_comparison.md +33 -0
  83. benchmarks/sdf_showcase/operations/boolean/difference_sphere_box.png +0 -0
  84. benchmarks/sdf_showcase/operations/boolean/union_sphere_box.png +0 -0
  85. benchmarks/sdf_showcase/operations/transformations/circular_array_sphere.png +0 -0
  86. benchmarks/sdf_showcase/operations/transformations/dilate_sphere.png +0 -0
  87. benchmarks/sdf_showcase/operations/transformations/mirror_sphere.png +0 -0
  88. benchmarks/sdf_showcase/operations/transformations/repeat_sphere.png +0 -0
  89. benchmarks/sdf_showcase/operations/transformations/revolve_circle.png +0 -0
  90. benchmarks/sdf_showcase/operations/transformations/shell_sphere.png +0 -0
  91. benchmarks/sdf_showcase/operations/transformations/twist_torus.png +0 -0
  92. benchmarks/sdf_showcase/primitives/2D/circle.png +0 -0
  93. benchmarks/sdf_showcase/primitives/2D/equilateral_triangle.png +0 -0
  94. benchmarks/sdf_showcase/primitives/2D/hexagon.png +0 -0
  95. benchmarks/sdf_showcase/primitives/2D/polygon_pentagon.png +0 -0
  96. benchmarks/sdf_showcase/primitives/2D/rectangle.png +0 -0
  97. benchmarks/sdf_showcase/primitives/2D/rounded_rectangle.png +0 -0
  98. benchmarks/sdf_showcase/primitives/3D/box.png +0 -0
  99. benchmarks/sdf_showcase/primitives/3D/capped_cone.png +0 -0
  100. benchmarks/sdf_showcase/primitives/3D/capped_cylinder.png +0 -0
  101. benchmarks/sdf_showcase/primitives/3D/capsule.png +0 -0
  102. benchmarks/sdf_showcase/primitives/3D/cone.png +0 -0
  103. benchmarks/sdf_showcase/primitives/3D/corner_spheres.png +0 -0
  104. benchmarks/sdf_showcase/primitives/3D/cross_ms.png +0 -0
  105. benchmarks/sdf_showcase/primitives/3D/cylinder.png +0 -0
  106. benchmarks/sdf_showcase/primitives/3D/dodecahedron.png +0 -0
  107. benchmarks/sdf_showcase/primitives/3D/ellipsoid.png +0 -0
  108. benchmarks/sdf_showcase/primitives/3D/icosahedron.png +0 -0
  109. benchmarks/sdf_showcase/primitives/3D/octahedron.png +0 -0
  110. benchmarks/sdf_showcase/primitives/3D/pyramid.png +0 -0
  111. benchmarks/sdf_showcase/primitives/3D/rounded_box.png +0 -0
  112. benchmarks/sdf_showcase/primitives/3D/rounded_cone.png +0 -0
  113. benchmarks/sdf_showcase/primitives/3D/rounded_cylinder.png +0 -0
  114. benchmarks/sdf_showcase/primitives/3D/sphere.png +0 -0
  115. benchmarks/sdf_showcase/primitives/3D/tetrahedron.png +0 -0
  116. benchmarks/sdf_showcase/primitives/3D/torus.png +0 -0
  117. benchmarks/sdf_showcase/primitives/3D/wireframe_box.png +0 -0
  118. deepsdfstruct-1.7.2.dist-info/METADATA +44 -0
  119. deepsdfstruct-1.7.2.dist-info/RECORD +165 -0
  120. deepsdfstruct-1.7.2.dist-info/WHEEL +5 -0
  121. deepsdfstruct-1.7.2.dist-info/licenses/LICENSE +208 -0
  122. deepsdfstruct-1.7.2.dist-info/licenses/NOTICE +67 -0
  123. deepsdfstruct-1.7.2.dist-info/scm_file_list.json +178 -0
  124. deepsdfstruct-1.7.2.dist-info/scm_version.json +8 -0
  125. deepsdfstruct-1.7.2.dist-info/top_level.txt +4 -0
  126. docs/Makefile +20 -0
  127. docs/api_reference.rst +6 -0
  128. docs/conf.py +60 -0
  129. docs/index.rst +136 -0
  130. docs/make.bat +35 -0
  131. docs/qr_code_github.png +0 -0
  132. docs/qr_code_paper.png +0 -0
  133. docs/readme_images/example_output_01.png +0 -0
  134. docs/readme_images/example_output_02.png +0 -0
  135. docs/readme_images/example_output_03.png +0 -0
  136. docs/readme_images/example_output_04.png +0 -0
  137. tests/data/chairs/1005.obj +282 -0
  138. tests/data/chairs/1024.obj +222 -0
  139. tests/data/chairs/README.md +1 -0
  140. tests/data/circular_balls_test_case.stl +0 -0
  141. tests/data/cone.stl +1794 -0
  142. tests/data/example_disconnectd_mesh.inp +1784 -0
  143. tests/data/example_line_mesh.vtk +0 -0
  144. tests/data/stanford_bunny.stl +0 -0
  145. tests/data/sweep_test_case.stl +0 -0
  146. tests/test_DOE.py +49 -0
  147. tests/test_elongate_sdf.py +195 -0
  148. tests/test_flexisquares.py +187 -0
  149. tests/test_generate_dataset.py +76 -0
  150. tests/test_lattice_evaluation.py +137 -0
  151. tests/test_mesh_export.py +137 -0
  152. tests/test_mesh_functions.py +49 -0
  153. tests/test_networks.py +71 -0
  154. tests/test_pretrained_models.py +40 -0
  155. tests/test_reconstruction.py +101 -0
  156. tests/test_sdf_from_mesh.py +52 -0
  157. tests/test_sdf_functions.py +117 -0
  158. tests/test_sdf_primitives.py +668 -0
  159. tests/test_sdf_trimesh_comparison.py +482 -0
  160. tests/test_splinepy_unitcells.py +64 -0
  161. tests/test_structural_optimization.py +178 -0
  162. tests/test_torch_spline.py +216 -0
  163. tests/test_train_model.py +110 -0
  164. tests/test_training_data_ids.py +41 -0
  165. tests/tmp_outputs/temp_file.txt +0 -0
@@ -0,0 +1,544 @@
1
+ """
2
+ Snappy-3D Lattice Unit Cell
3
+ ===========================
4
+
5
+ This module implements a 3D snap-through lattice unit cell using splinepy.
6
+ The snappy structure features thin and thick trusses that can collide,
7
+ enabling snap-through mechanical behavior.
8
+
9
+ The thickness can vary along the z-direction, allowing for graded properties
10
+ and tunable mechanical response.
11
+
12
+ Author: Michael Kofler, 2024-06-27
13
+ Version: 0.1
14
+ """
15
+
16
+ import numpy as _np
17
+
18
+ from splinepy.bezier import Bezier as _Bezier
19
+ from splinepy.microstructure.tiles.tile_base import TileBase as _TileBase
20
+
21
+
22
+ class Snappy3D(_TileBase):
23
+ """Snap-through tile consisting of a thin truss and a thick truss that
24
+ collide into each other. The thickness can vary in z-direction.
25
+ Version: 0.1
26
+ Author: Michael Kofler, 2024-06-27
27
+ """ # noqa: E501
28
+
29
+ _dim = 3
30
+ _para_dim = 3
31
+ # dummy values - not used
32
+ _evaluation_points = _np.array([[0.5, 0.5, 0.5]])
33
+ _n_info_per_eval_point = 1
34
+
35
+ def _closing_tile(
36
+ self,
37
+ parameters=None,
38
+ parameter_sensitivities=None, # TODO
39
+ closure=None,
40
+ contact_length=0.1,
41
+ a=0.1,
42
+ b=0.2,
43
+ r=0.15,
44
+ **kwargs, # noqa ARG002
45
+ ):
46
+ """Create a closing tile to match with closed surface.
47
+
48
+ Parameters
49
+ ----------
50
+ parameters: np.ndarray(1, 1)
51
+ currently unused
52
+ parameter_sensitivities: np.ndarray
53
+ Describes the parameter sensitivities with respect to some design
54
+ variable. In case the design variables directly apply to the
55
+ parameter itself, they evaluate as delta_ij unused
56
+ closure : str
57
+ string specifying the closing dimensions (e.g., x_min)
58
+ contact_length : float
59
+ the length of the wall that contacts neighboring microstructures
60
+ a : float
61
+ height/ thickness of the thinner/upper beam
62
+ b : float
63
+ height/ thickness of the lower/thicker beam
64
+ r : float
65
+ 'radius' of the cubic bezier
66
+
67
+ Results
68
+ -------
69
+ spline_list : list
70
+ derivatives: list<list<splines>> / None
71
+ """
72
+ if closure is None:
73
+ raise ValueError("No closing direction given")
74
+
75
+ self.check_params(parameters)
76
+
77
+ if parameter_sensitivities is not None:
78
+ raise NotImplementedError(
79
+ "Derivatives are not implemented for this tile yet"
80
+ )
81
+
82
+ spline_list = []
83
+ v_zero = 0.0
84
+ v_one_half = 0.5
85
+ v_one = 1.0
86
+ cl_2 = contact_length * 0.5
87
+ cl_2_inv = 1 - contact_length * 0.5
88
+ a_inv = v_one - a
89
+
90
+ if closure == "y_min":
91
+ # set points:
92
+ spline_1 = _np.array(
93
+ [[v_zero, v_zero], [cl_2, v_zero], [v_zero, b], [cl_2, b]]
94
+ )
95
+
96
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_1))
97
+ spline_2 = _np.array(
98
+ [[cl_2_inv, v_zero], [v_one, v_zero], [cl_2_inv, b], [v_one, b]]
99
+ )
100
+
101
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_2))
102
+ spline_3 = _np.array(
103
+ [[v_zero, a_inv], [cl_2, a_inv], [v_zero, v_one], [cl_2, v_one]]
104
+ )
105
+
106
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_3))
107
+ spline_4 = _np.array(
108
+ [[cl_2_inv, a_inv], [v_one, a_inv], [cl_2_inv, v_one], [v_one, v_one]]
109
+ )
110
+
111
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_4))
112
+
113
+ spline_5 = _np.array(
114
+ [
115
+ [v_one_half - cl_2, v_zero],
116
+ [v_one_half + cl_2, v_zero],
117
+ [v_one_half - cl_2, v_one_half],
118
+ [v_one_half + cl_2, v_one_half],
119
+ ]
120
+ )
121
+
122
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_5))
123
+
124
+ spline_6 = _np.array(
125
+ [
126
+ [v_one_half - cl_2, v_one_half],
127
+ [v_one_half + cl_2, v_one_half],
128
+ [v_one_half - cl_2, v_one_half + a],
129
+ [v_one_half + cl_2, v_one_half + a],
130
+ ]
131
+ )
132
+
133
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_6))
134
+
135
+ spline_7 = _np.array(
136
+ [
137
+ [cl_2, v_zero],
138
+ [cl_2 + r, v_zero],
139
+ [v_one_half - cl_2 - r, v_zero],
140
+ [v_one_half - cl_2, v_zero],
141
+ [cl_2, b],
142
+ [cl_2 + r, b],
143
+ [v_one_half - cl_2 - r, v_one_half],
144
+ [v_one_half - cl_2, v_one_half],
145
+ ]
146
+ )
147
+
148
+ spline_list.append(_Bezier(degrees=[3, 1], control_points=spline_7))
149
+
150
+ spline_8 = _np.array(
151
+ [
152
+ [cl_2, v_zero],
153
+ [cl_2 + r, v_zero],
154
+ [v_one_half - cl_2 - r, v_zero],
155
+ [v_one_half - cl_2, v_zero],
156
+ [cl_2, v_one_half],
157
+ [cl_2 + r, v_one_half],
158
+ [v_one_half - cl_2 - r, b],
159
+ [v_one_half - cl_2, b],
160
+ ]
161
+ ) + [v_one_half, v_zero]
162
+
163
+ spline_list.append(_Bezier(degrees=[3, 1], control_points=spline_8))
164
+
165
+ spline_9 = _np.array(
166
+ [
167
+ [cl_2, a_inv],
168
+ [cl_2 + r, a_inv],
169
+ [v_one_half - cl_2 - r, v_one_half],
170
+ [v_one_half - cl_2, v_one_half],
171
+ [cl_2, v_one],
172
+ [cl_2 + r, v_one],
173
+ [v_one_half - cl_2 - r, v_one_half + a],
174
+ [v_one_half - cl_2, v_one_half + a],
175
+ ]
176
+ )
177
+
178
+ spline_list.append(_Bezier(degrees=[3, 1], control_points=spline_9))
179
+
180
+ spline_10 = _np.array(
181
+ [
182
+ [cl_2, v_one_half],
183
+ [cl_2 + r, v_one_half],
184
+ [v_one_half - cl_2 - r, a_inv],
185
+ [v_one_half - cl_2, a_inv],
186
+ [cl_2, v_one_half + a],
187
+ [cl_2 + r, v_one_half + a],
188
+ [v_one_half - cl_2 - r, v_one],
189
+ [v_one_half - cl_2, v_one],
190
+ ]
191
+ ) + [v_one_half, v_zero]
192
+
193
+ spline_list.append(_Bezier(degrees=[3, 1], control_points=spline_10))
194
+ return spline_list
195
+ elif closure == "y_max":
196
+ spline_1 = _np.array(
197
+ [[v_zero, v_zero], [cl_2, v_zero], [v_zero, v_one], [cl_2, v_one]]
198
+ )
199
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_1))
200
+ spline_2 = _np.array(
201
+ [[cl_2_inv, v_zero], [v_one, v_zero], [cl_2_inv, v_one], [v_one, v_one]]
202
+ )
203
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_2))
204
+ spline_3 = _np.array(
205
+ [
206
+ [v_one_half - cl_2, v_one_half - b],
207
+ [v_one_half + cl_2, v_one_half - b],
208
+ [v_one_half - cl_2, v_one],
209
+ [v_one_half + cl_2, v_one],
210
+ ]
211
+ )
212
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_3))
213
+ spline_4 = _np.array(
214
+ [
215
+ [cl_2, v_zero],
216
+ [cl_2 + r, v_zero],
217
+ [v_one_half - cl_2 - r, v_one_half - b],
218
+ [v_one_half - cl_2, v_one_half - b],
219
+ [cl_2, v_one],
220
+ [cl_2 + r, v_one],
221
+ [v_one_half - cl_2 - r, v_one],
222
+ [v_one_half - cl_2, v_one],
223
+ ]
224
+ )
225
+ spline_list.append(_Bezier(degrees=[3, 1], control_points=spline_4))
226
+ spline_5 = _np.array(
227
+ [
228
+ [cl_2, v_one_half - b],
229
+ [cl_2 + r, v_one_half - b],
230
+ [v_one_half - cl_2 - r, v_zero],
231
+ [v_one_half - cl_2, v_zero],
232
+ [cl_2, v_one],
233
+ [cl_2 + r, v_one],
234
+ [v_one_half - cl_2 - r, v_one],
235
+ [v_one_half - cl_2, v_one],
236
+ ]
237
+ ) + [v_one_half, v_zero]
238
+
239
+ spline_list.append(_Bezier(degrees=[3, 1], control_points=spline_5))
240
+ return (spline_list, None)
241
+ else:
242
+ raise ValueError("Closing tile is only implemented for y-enclosure")
243
+
244
+ def create_tile(
245
+ self,
246
+ parameters=None,
247
+ parameter_sensitivities=None, # TODO
248
+ contact_length=0.1,
249
+ a=0.1,
250
+ b=0.1,
251
+ c=0.3,
252
+ r=0.15,
253
+ closure=None,
254
+ **kwargs, # noqa ARG002
255
+ ):
256
+ """Create a microtile based on the parameters that describe the wall
257
+ thicknesses.
258
+
259
+ Thickness parameters are used to describe the inner radius of the
260
+ outward facing branches
261
+
262
+ Parameters
263
+ ----------
264
+ parameters : np.array
265
+ Currently, no parameter is used, (First test)
266
+ parameter_sensitivities: list(np.ndarray)
267
+ Describes the parameter sensitivities with respect to some design
268
+ variable. In case the design variables directly apply to the
269
+ parameter itself, they evaluate as delta_ij, currently unused
270
+ contact_length : float
271
+ the length of the wall that contacts neighboring microstructures
272
+ a : float
273
+ height/ thickness of the thinner/upper beam
274
+ b : float
275
+ height/ thickness of the lower/thicker beam
276
+ c : float
277
+ offset to the upper beam (for consistent snap-through must fulfill
278
+ 2*c<1-b)
279
+ r : float
280
+ 'radius' of the cubic bezier
281
+ closure : str
282
+ string specifying the closing dimensions (e.g., x_min)
283
+
284
+ Returns
285
+ -------
286
+ microtile_list : list(splines)
287
+ derivatives: list<list<splines>> / None
288
+ """
289
+
290
+ for param in [a, b, c, r, contact_length]:
291
+ if not isinstance(param, float):
292
+ raise ValueError(f"Invalid Type, {param} is not float")
293
+ if param < 0:
294
+ raise ValueError("Invalid parameter, must be > 0.")
295
+
296
+ if not ((contact_length > 0) and (contact_length < 0.49)):
297
+ raise ValueError("The length of a side must be in (0.01, 0.49)")
298
+
299
+ # Check horizontal parameters
300
+ if not ((r + contact_length) < 0.5):
301
+ raise ValueError(
302
+ "Inconsistent parameters, must fulfill : 2*r + contact_length" " < 0.5"
303
+ )
304
+
305
+ # Check vertical parameters
306
+ if not ((2 * c + b) < 1.0) or a > c:
307
+ raise ValueError("Inconsistent parameters, must be 2*c<1-c and a<c")
308
+
309
+ if parameters is None:
310
+ parameters = _np.array([[0.4]])
311
+
312
+ if parameter_sensitivities is not None:
313
+ raise NotImplementedError(
314
+ "Derivatives are not implemented for this tile yet"
315
+ )
316
+
317
+ if closure is not None:
318
+ return self._closing_tile(
319
+ parameters=None,
320
+ parameter_sensitivities=parameter_sensitivities,
321
+ closure=closure,
322
+ contact_length=contact_length,
323
+ a=a,
324
+ b=b,
325
+ r=r,
326
+ **kwargs,
327
+ )
328
+
329
+ v_zero = 0.0
330
+ v_one_half = 0.5
331
+ v_one = 1.0
332
+ cl_2 = contact_length * 0.5
333
+ cl_2_inv = 1 - contact_length * 0.5
334
+ a_inv = v_one - a
335
+ thickness = parameters[0, 0]
336
+
337
+ spline_list = []
338
+
339
+ # set points:
340
+ spline_1 = _np.array([[v_zero, v_zero], [cl_2, v_zero], [v_zero, b], [cl_2, b]])
341
+
342
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_1))
343
+ spline_2 = _np.array(
344
+ [[cl_2_inv, v_zero], [v_one, v_zero], [cl_2_inv, b], [v_one, b]]
345
+ )
346
+
347
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_2))
348
+ spline_3 = _np.array(
349
+ [[v_zero, a_inv], [cl_2, a_inv], [v_zero, v_one], [cl_2, v_one]]
350
+ )
351
+
352
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_3))
353
+ spline_4 = _np.array(
354
+ [[cl_2_inv, a_inv], [v_one, a_inv], [cl_2_inv, v_one], [v_one, v_one]]
355
+ )
356
+
357
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_4))
358
+
359
+ spline_5 = _np.array(
360
+ [
361
+ [v_one_half - cl_2, v_one_half - b],
362
+ [v_one_half + cl_2, v_one_half - b],
363
+ [v_one_half - cl_2, v_one_half],
364
+ [v_one_half + cl_2, v_one_half],
365
+ ]
366
+ )
367
+
368
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_5))
369
+
370
+ spline_6 = _np.array(
371
+ [
372
+ [v_one_half - cl_2, v_one_half],
373
+ [v_one_half + cl_2, v_one_half],
374
+ [v_one_half - cl_2, v_one_half + a],
375
+ [v_one_half + cl_2, v_one_half + a],
376
+ ]
377
+ )
378
+
379
+ spline_list.append(_Bezier(degrees=[1, 1], control_points=spline_6))
380
+
381
+ spline_7 = _np.array(
382
+ [
383
+ [cl_2, v_zero],
384
+ [cl_2 + r, v_zero],
385
+ [v_one_half - cl_2 - r, v_one_half - b],
386
+ [v_one_half - cl_2, v_one_half - b],
387
+ [cl_2, b],
388
+ [cl_2 + r, b],
389
+ [v_one_half - cl_2 - r, v_one_half],
390
+ [v_one_half - cl_2, v_one_half],
391
+ ]
392
+ )
393
+
394
+ spline_list.append(_Bezier(degrees=[3, 1], control_points=spline_7))
395
+
396
+ spline_8 = _np.array(
397
+ [
398
+ [cl_2, v_one_half - b],
399
+ [cl_2 + r, v_one_half - b],
400
+ [v_one_half - cl_2 - r, v_zero],
401
+ [v_one_half - cl_2, v_zero],
402
+ [cl_2, v_one_half],
403
+ [cl_2 + r, v_one_half],
404
+ [v_one_half - cl_2 - r, b],
405
+ [v_one_half - cl_2, b],
406
+ ]
407
+ ) + [v_one_half, v_zero]
408
+
409
+ spline_list.append(_Bezier(degrees=[3, 1], control_points=spline_8))
410
+
411
+ spline_9 = _np.array(
412
+ [
413
+ [cl_2, a_inv],
414
+ [cl_2 + r, a_inv],
415
+ [v_one_half - cl_2 - r, v_one_half],
416
+ [v_one_half - cl_2, v_one_half],
417
+ [cl_2, v_one],
418
+ [cl_2 + r, v_one],
419
+ [v_one_half - cl_2 - r, v_one_half + a],
420
+ [v_one_half - cl_2, v_one_half + a],
421
+ ]
422
+ )
423
+
424
+ spline_list.append(_Bezier(degrees=[3, 1], control_points=spline_9))
425
+
426
+ spline_10 = _np.array(
427
+ [
428
+ [cl_2, v_one_half],
429
+ [cl_2 + r, v_one_half],
430
+ [v_one_half - cl_2 - r, a_inv],
431
+ [v_one_half - cl_2, a_inv],
432
+ [cl_2, v_one_half + a],
433
+ [cl_2 + r, v_one_half + a],
434
+ [v_one_half - cl_2 - r, v_one],
435
+ [v_one_half - cl_2, v_one],
436
+ ]
437
+ ) + [v_one_half, v_zero]
438
+
439
+ spline_list.append(_Bezier(degrees=[3, 1], control_points=spline_10))
440
+ # extrude tiles to create thickness
441
+ spline_list_extruded = [
442
+ mt.copy().create.extruded(extrusion_vector=[0, 0, 1]) for mt in spline_list
443
+ ]
444
+ for sle in spline_list_extruded:
445
+ sle.elevate_degrees([2])
446
+ # vector to change curvature over the thickness
447
+ vec = _np.array([0, thickness, 0])
448
+
449
+ # lower left
450
+ spline_list_extruded[6].control_points[10] = (
451
+ spline_list_extruded[6].control_points[10] - vec
452
+ )
453
+ spline_list_extruded[6].control_points[11] = (
454
+ spline_list_extruded[6].control_points[11] - vec
455
+ )
456
+ spline_list_extruded[6].control_points[12] = (
457
+ spline_list_extruded[6].control_points[12] + vec
458
+ )
459
+ spline_list_extruded[6].control_points[13] = (
460
+ spline_list_extruded[6].control_points[13] + vec
461
+ )
462
+
463
+ # lower right
464
+ spline_list_extruded[7].control_points[14] = (
465
+ spline_list_extruded[7].control_points[14] + vec
466
+ )
467
+ spline_list_extruded[7].control_points[15] = (
468
+ spline_list_extruded[7].control_points[15] + vec
469
+ )
470
+ spline_list_extruded[7].control_points[8] = (
471
+ spline_list_extruded[7].control_points[8] - vec
472
+ )
473
+ spline_list_extruded[7].control_points[9] = (
474
+ spline_list_extruded[7].control_points[9] - vec
475
+ )
476
+ # upper left
477
+ spline_list_extruded[8].control_points[14] = (
478
+ spline_list_extruded[8].control_points[14] + vec
479
+ )
480
+ spline_list_extruded[8].control_points[15] = (
481
+ spline_list_extruded[8].control_points[15] + vec
482
+ )
483
+ spline_list_extruded[8].control_points[8] = (
484
+ spline_list_extruded[8].control_points[8] - vec
485
+ )
486
+ spline_list_extruded[8].control_points[9] = (
487
+ spline_list_extruded[8].control_points[9] - vec
488
+ )
489
+
490
+ # upper right
491
+ spline_list_extruded[9].control_points[10] = (
492
+ spline_list_extruded[9].control_points[10] - vec
493
+ )
494
+ spline_list_extruded[9].control_points[11] = (
495
+ spline_list_extruded[9].control_points[11] - vec
496
+ )
497
+ spline_list_extruded[9].control_points[12] = (
498
+ spline_list_extruded[9].control_points[12] + vec
499
+ )
500
+ spline_list_extruded[9].control_points[13] = (
501
+ spline_list_extruded[9].control_points[13] + vec
502
+ )
503
+
504
+ ########################## cubes ########################################################
505
+ p1 = spline_list_extruded[0].control_points[6]
506
+ p2 = spline_list_extruded[0].control_points[7]
507
+ spline_list_extruded[0].control_points[6] = p1 + vec
508
+ spline_list_extruded[0].control_points[7] = p2 + vec
509
+
510
+ ###
511
+ p1 = spline_list_extruded[1].control_points[6]
512
+ p2 = spline_list_extruded[1].control_points[7]
513
+ spline_list_extruded[1].control_points[6] = p1 + vec
514
+ spline_list_extruded[1].control_points[7] = p2 + vec
515
+
516
+ ###
517
+ p1 = spline_list_extruded[2].control_points[4]
518
+ p2 = spline_list_extruded[2].control_points[5]
519
+ spline_list_extruded[2].control_points[4] = p1 - vec
520
+ spline_list_extruded[2].control_points[5] = p2 - vec
521
+
522
+ ###
523
+ p1 = spline_list_extruded[3].control_points[5]
524
+ p2 = spline_list_extruded[3].control_points[4]
525
+ spline_list_extruded[3].control_points[5] = p1 - vec
526
+ spline_list_extruded[3].control_points[4] = p2 - vec
527
+
528
+ ###
529
+ p1 = spline_list_extruded[4].control_points[4]
530
+ p2 = spline_list_extruded[4].control_points[5]
531
+ spline_list_extruded[4].control_points[4] = p1 - vec
532
+ spline_list_extruded[4].control_points[5] = p2 - vec
533
+
534
+ ###
535
+ p1 = spline_list_extruded[5].control_points[6]
536
+ p2 = spline_list_extruded[5].control_points[7]
537
+ spline_list_extruded[5].control_points[6] = p1 + vec
538
+ spline_list_extruded[5].control_points[7] = p2 + vec
539
+ for spline in spline_list_extruded:
540
+ temp_pts = spline.control_points.copy()
541
+ spline.control_points[:, 0] = temp_pts[:, 1]
542
+ spline.control_points[:, 1] = temp_pts[:, 2]
543
+ spline.control_points[:, 2] = temp_pts[:, 0]
544
+ return (spline_list_extruded, None)