pytetwild 0.1.0__cp310-cp310-win_amd64.whl → 0.2.2__cp310-cp310-win_amd64.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.
- pytetwild/PyfTetWildWrapper.pyd +0 -0
- pytetwild/PyfTetWildWrapper.pyi +29 -0
- pytetwild/__init__.py +3 -3
- pytetwild/pytetwild.py +232 -57
- pytetwild-0.2.2.dist-info/DELVEWHEEL +2 -0
- {pytetwild-0.1.0.dist-info → pytetwild-0.2.2.dist-info}/METADATA +55 -20
- pytetwild-0.2.2.dist-info/RECORD +14 -0
- pytetwild-0.1.0.dist-info/DELVEWHEEL +0 -2
- pytetwild-0.1.0.dist-info/RECORD +0 -13
- {pytetwild-0.1.0.dist-info → pytetwild-0.2.2.dist-info}/WHEEL +0 -0
- {pytetwild-0.1.0.dist-info → pytetwild-0.2.2.dist-info}/licenses/LICENSE +0 -0
pytetwild/PyfTetWildWrapper.pyd
CHANGED
|
Binary file
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from numpy.typing import NDArray
|
|
3
|
+
|
|
4
|
+
def tetrahedralize_mesh(
|
|
5
|
+
vertices: NDArray[np.float64],
|
|
6
|
+
faces: NDArray[np.uint32],
|
|
7
|
+
optimize: bool,
|
|
8
|
+
skip_simplify: bool,
|
|
9
|
+
edge_length_r: float,
|
|
10
|
+
edge_length_abs: float,
|
|
11
|
+
epsilon: float,
|
|
12
|
+
stop_energy: float,
|
|
13
|
+
coarsen: bool,
|
|
14
|
+
num_threads: int,
|
|
15
|
+
num_opt_iter: int,
|
|
16
|
+
loglevel: int,
|
|
17
|
+
quiet: bool,
|
|
18
|
+
vtk_ordering: bool,
|
|
19
|
+
) -> tuple[NDArray[np.float64], NDArray[np.int32]]: ...
|
|
20
|
+
def tetrahedralize_csg(
|
|
21
|
+
csg_file: str,
|
|
22
|
+
epsilon: float,
|
|
23
|
+
edge_length_r: float,
|
|
24
|
+
stop_energy: float,
|
|
25
|
+
coarsen: bool,
|
|
26
|
+
num_threads: int,
|
|
27
|
+
log_level: int,
|
|
28
|
+
vtk_ordering: bool,
|
|
29
|
+
) -> tuple[NDArray[np.float64], NDArray[np.int32], NDArray[np.int32]]: ...
|
pytetwild/__init__.py
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
# start delvewheel patch
|
|
5
|
-
def
|
|
5
|
+
def _delvewheel_patch_1_12_0():
|
|
6
6
|
import os
|
|
7
7
|
if os.path.isdir(libs_dir := os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, 'pytetwild.libs'))):
|
|
8
8
|
os.add_dll_directory(libs_dir)
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
del
|
|
11
|
+
_delvewheel_patch_1_12_0()
|
|
12
|
+
del _delvewheel_patch_1_12_0
|
|
13
13
|
# end delvewheel patch
|
|
14
14
|
|
|
15
15
|
from ._version import __version__ # noqa: F401
|
pytetwild/pytetwild.py
CHANGED
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
import warnings
|
|
4
4
|
import numpy as np
|
|
5
|
-
from pytetwild import PyfTetWildWrapper
|
|
6
|
-
from typing import
|
|
7
|
-
|
|
5
|
+
from pytetwild import PyfTetWildWrapper
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
from numpy.typing import NDArray
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
10
|
import pyvista as pv
|
|
11
11
|
|
|
12
|
+
VTK_UNSIGNED_CHAR = 3
|
|
13
|
+
VTK_TETRA = 10
|
|
14
|
+
VTK_QUADRATIC_TETRA = 24
|
|
15
|
+
|
|
12
16
|
|
|
13
17
|
def _check_edge_length(edge_length_fac: float) -> None:
|
|
14
18
|
"""Check edge length.
|
|
@@ -19,14 +23,84 @@ def _check_edge_length(edge_length_fac: float) -> None:
|
|
|
19
23
|
Tetrahedral edge length as a function of bounding box diagonal. The
|
|
20
24
|
default ideal edge length is bb/20 (bounding box divided by 20).
|
|
21
25
|
|
|
22
|
-
|
|
23
26
|
"""
|
|
24
27
|
if edge_length_fac > 1.0 or edge_length_fac < 0.0 + 1e-16:
|
|
25
28
|
raise ValueError("Edge length factor must be between 1e-16 and 1.0")
|
|
26
29
|
|
|
27
30
|
|
|
31
|
+
def _ugrid_from_regular_cells(
|
|
32
|
+
points: NDArray[np.float32] | NDArray[np.float64],
|
|
33
|
+
cells: NDArray[np.int32],
|
|
34
|
+
) -> "pv.UnstructuredGrid":
|
|
35
|
+
"""
|
|
36
|
+
Create an UnstructuredGrid from points and fixed-size cells.
|
|
37
|
+
|
|
38
|
+
Parameters
|
|
39
|
+
----------
|
|
40
|
+
points : np.ndarray[np.float64]
|
|
41
|
+
Point coordinates.
|
|
42
|
+
cells : np.ndarray[np.int32]
|
|
43
|
+
Cell connectivity without padding. Cell type inferred from shape.
|
|
44
|
+
|
|
45
|
+
Returns
|
|
46
|
+
-------
|
|
47
|
+
pyvista.UnstructuredGrid
|
|
48
|
+
Unstructured grid.
|
|
49
|
+
|
|
50
|
+
"""
|
|
51
|
+
try:
|
|
52
|
+
import pyvista.core as pv
|
|
53
|
+
except:
|
|
54
|
+
raise ModuleNotFoundError(
|
|
55
|
+
"Install PyVista to use this feature with:\n\npip install pytetwild[all]"
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
from vtkmodules.vtkCommonCore import vtkTypeInt32Array
|
|
59
|
+
from vtkmodules.util.numpy_support import numpy_to_vtk
|
|
60
|
+
from vtkmodules.vtkCommonDataModel import vtkCellArray
|
|
61
|
+
|
|
62
|
+
if cells.ndim != 2:
|
|
63
|
+
raise ValueError("cells must be 2D")
|
|
64
|
+
|
|
65
|
+
grid = pv.UnstructuredGrid()
|
|
66
|
+
grid.points = points
|
|
67
|
+
|
|
68
|
+
n_cells, n_nodes_per_cell = cells.shape
|
|
69
|
+
vtk_dtype = vtkTypeInt32Array().GetDataType()
|
|
70
|
+
offsets = np.arange(0, n_cells * n_nodes_per_cell + 1, n_nodes_per_cell, dtype=np.int32)
|
|
71
|
+
offsets_vtk = numpy_to_vtk(offsets, deep=False, array_type=vtk_dtype)
|
|
72
|
+
conn_vtk = numpy_to_vtk(cells.ravel(), deep=False, array_type=vtk_dtype)
|
|
73
|
+
|
|
74
|
+
cell_array = vtkCellArray()
|
|
75
|
+
cell_array.SetData(offsets_vtk, conn_vtk)
|
|
76
|
+
|
|
77
|
+
if n_nodes_per_cell == 4:
|
|
78
|
+
cell_type = VTK_TETRA
|
|
79
|
+
elif n_nodes_per_cell == 10:
|
|
80
|
+
cell_type = VTK_QUADRATIC_TETRA
|
|
81
|
+
else:
|
|
82
|
+
raise ValueError(f"Unsupported number of nodes per cells {n_nodes_per_cell}")
|
|
83
|
+
|
|
84
|
+
celltypes = numpy_to_vtk(
|
|
85
|
+
np.full(n_cells, cell_type, dtype=np.uint8), deep=False, array_type=VTK_UNSIGNED_CHAR
|
|
86
|
+
)
|
|
87
|
+
grid.SetCells(celltypes, cell_array)
|
|
88
|
+
return grid
|
|
89
|
+
|
|
90
|
+
|
|
28
91
|
def tetrahedralize_pv(
|
|
29
|
-
mesh: "pv.PolyData",
|
|
92
|
+
mesh: "pv.PolyData",
|
|
93
|
+
edge_length_fac: float = 0.05,
|
|
94
|
+
edge_length_abs: float | None = None,
|
|
95
|
+
optimize: bool = True,
|
|
96
|
+
simplify: bool = True,
|
|
97
|
+
epsilon: float = 1e-3,
|
|
98
|
+
stop_energy: float = 10.0,
|
|
99
|
+
coarsen: bool = False,
|
|
100
|
+
num_threads: int = 0,
|
|
101
|
+
num_opt_iter: int = 80,
|
|
102
|
+
loglevel: int = 3,
|
|
103
|
+
quiet: bool = True,
|
|
30
104
|
) -> "pv.UnstructuredGrid":
|
|
31
105
|
"""
|
|
32
106
|
Convert a PyVista surface mesh to a PyVista unstructured grid.
|
|
@@ -34,13 +108,36 @@ def tetrahedralize_pv(
|
|
|
34
108
|
Parameters
|
|
35
109
|
----------
|
|
36
110
|
mesh : pv.PolyData
|
|
37
|
-
The input surface mesh.
|
|
111
|
+
The input surface mesh. Should be composed of all triangles.
|
|
38
112
|
edge_length_fac : float, default: 0.05
|
|
39
113
|
Tetrahedral edge length as a function of bounding box diagonal. The
|
|
40
|
-
default ideal edge length is bb/20 (bounding box divided by
|
|
41
|
-
|
|
114
|
+
default ideal edge length is ``bb/20`` (bounding box divided by
|
|
115
|
+
20). Ignored when ``edge_length_abs`` is input.
|
|
116
|
+
edge_length_abs : float, optional
|
|
117
|
+
Absolute ideal edge length. When input ``edge_length_fac`` is ignored.
|
|
118
|
+
optimize : bool, default: True
|
|
42
119
|
Improve the minimum scaled Jacobean for each cell. This leads to higher
|
|
43
|
-
cell quality at the expense of computation time.
|
|
120
|
+
cell quality at the expense of computation time. Optimization level is
|
|
121
|
+
dependent on ``stop_energy`` and ``num_opt_iter``.
|
|
122
|
+
simplify : bool, default: True
|
|
123
|
+
Simplfiy the input mesh surface before tetrahedralization.
|
|
124
|
+
epsilon : float, default 1e-3
|
|
125
|
+
Envelop size, specifying the maximum distance of the output surface
|
|
126
|
+
from the input surface, relative to the bounding box size.
|
|
127
|
+
stop_energy : float, default: 10.0
|
|
128
|
+
The mesh optimization stops when the conformal AMIPS energy reaches
|
|
129
|
+
``stop_energy``.
|
|
130
|
+
coarsen : bool, default: False
|
|
131
|
+
Coarsen the output as much as possible, while maintaining the mesh
|
|
132
|
+
quality.
|
|
133
|
+
num_threads : int, default: 0
|
|
134
|
+
Set number of threads used. 0 (default) uses all available cores.
|
|
135
|
+
num_opt_iter : int, default: 80
|
|
136
|
+
Maximum number of optimization iterations if ``optimize=True``.
|
|
137
|
+
loglevel : int, default: 6
|
|
138
|
+
Set log level (0 = most verbose, 6 = minimal output).
|
|
139
|
+
quiet : bool, default: False
|
|
140
|
+
Disable all output. Overrides ``loglevel``.
|
|
44
141
|
|
|
45
142
|
Returns
|
|
46
143
|
-------
|
|
@@ -64,7 +161,7 @@ def tetrahedralize_pv(
|
|
|
64
161
|
|
|
65
162
|
"""
|
|
66
163
|
try:
|
|
67
|
-
import pyvista as pv
|
|
164
|
+
import pyvista.core as pv
|
|
68
165
|
except:
|
|
69
166
|
raise ModuleNotFoundError(
|
|
70
167
|
"Install PyVista to use this feature with:\n\npip install pytetwild[all]"
|
|
@@ -72,55 +169,101 @@ def tetrahedralize_pv(
|
|
|
72
169
|
|
|
73
170
|
if not isinstance(mesh, pv.PolyData):
|
|
74
171
|
raise TypeError(f"`mesh` must be a pyvista.PolyData, got {type(mesh)}")
|
|
75
|
-
|
|
76
172
|
if not mesh.is_all_triangles:
|
|
77
173
|
warnings.warn(
|
|
78
174
|
"Input mesh is not all triangles. Either call `.triangulate()`"
|
|
79
175
|
" beforehand to suppress this warning or use an all triangle mesh."
|
|
80
176
|
)
|
|
81
177
|
mesh = mesh.triangulate()
|
|
82
|
-
|
|
83
178
|
_check_edge_length(edge_length_fac)
|
|
179
|
+
|
|
180
|
+
if edge_length_abs is None:
|
|
181
|
+
edge_length_abs = 0.0
|
|
182
|
+
|
|
84
183
|
vertices = mesh.points.astype(np.float64, copy=False)
|
|
85
|
-
faces = mesh.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
cells = np.hstack(
|
|
93
|
-
[
|
|
94
|
-
np.full((tetrahedral_mesh_tetrahedra.shape[0], 1), 4, dtype=np.int32),
|
|
95
|
-
tetrahedral_mesh_tetrahedra,
|
|
96
|
-
]
|
|
97
|
-
)
|
|
98
|
-
cell_types = np.full(tetrahedral_mesh_tetrahedra.shape[0], 10, dtype=np.uint8)
|
|
184
|
+
faces = mesh._connectivity_array.reshape(-1, 3)
|
|
185
|
+
if faces.dtype == np.int32:
|
|
186
|
+
# we can cheat here and just treat it as unsigned 32 (assuming no negative indices)
|
|
187
|
+
faces_unsigned = faces.view(np.uint32)
|
|
188
|
+
else:
|
|
189
|
+
faces_unsigned = faces.astype(np.uint32, copy=False)
|
|
99
190
|
|
|
100
|
-
|
|
191
|
+
skip_simplify = not simplify
|
|
192
|
+
vtk_ordering = True
|
|
193
|
+
tmesh_v, tmesh_c = PyfTetWildWrapper.tetrahedralize_mesh(
|
|
194
|
+
vertices,
|
|
195
|
+
faces_unsigned,
|
|
196
|
+
optimize,
|
|
197
|
+
skip_simplify,
|
|
198
|
+
edge_length_fac,
|
|
199
|
+
edge_length_abs,
|
|
200
|
+
epsilon,
|
|
201
|
+
stop_energy,
|
|
202
|
+
coarsen,
|
|
203
|
+
num_threads,
|
|
204
|
+
num_opt_iter,
|
|
205
|
+
loglevel,
|
|
206
|
+
quiet,
|
|
207
|
+
vtk_ordering,
|
|
208
|
+
)
|
|
209
|
+
return _ugrid_from_regular_cells(tmesh_v, tmesh_c)
|
|
101
210
|
|
|
102
211
|
|
|
103
212
|
def tetrahedralize(
|
|
104
|
-
vertices:
|
|
105
|
-
faces:
|
|
106
|
-
optimize: bool = True,
|
|
213
|
+
vertices: NDArray[np.float32] | NDArray[np.float64],
|
|
214
|
+
faces: NDArray[np.int32],
|
|
107
215
|
edge_length_fac: float = 0.05,
|
|
108
|
-
|
|
216
|
+
edge_length_abs: float | None = None,
|
|
217
|
+
optimize: bool = True,
|
|
218
|
+
simplify: bool = True,
|
|
219
|
+
epsilon: float = 1e-3,
|
|
220
|
+
stop_energy: float = 10.0,
|
|
221
|
+
coarsen: bool = False,
|
|
222
|
+
num_threads: int = 0,
|
|
223
|
+
num_opt_iter: int = 80,
|
|
224
|
+
loglevel: int = 3,
|
|
225
|
+
quiet: bool = True,
|
|
226
|
+
vtk_ordering: bool = False,
|
|
227
|
+
) -> tuple[NDArray[np.float64], NDArray[np.int32]]:
|
|
109
228
|
"""
|
|
110
229
|
Convert mesh vertices and faces to a tetrahedral mesh.
|
|
111
230
|
|
|
112
231
|
Parameters
|
|
113
232
|
----------
|
|
114
|
-
vertices : np.ndarray[
|
|
233
|
+
vertices : np.ndarray[np.float32] | np.ndarray[np.float64]
|
|
115
234
|
The vertices of the mesh.
|
|
116
|
-
faces : np.ndarray
|
|
235
|
+
faces : np.ndarray[np.int32]
|
|
117
236
|
The faces of the mesh.
|
|
237
|
+
edge_length_fac : float, default: 0.05
|
|
238
|
+
Tetrahedral edge length as a function of bounding box diagonal. The
|
|
239
|
+
default ideal edge length is bb/20 (bounding box divided by
|
|
240
|
+
20). Ignored when ``edge_length_abs`` is input.
|
|
241
|
+
edge_length_abs : float, optional
|
|
242
|
+
Absolute ideal edge length. When input ``edge_length_fac`` is ignored.
|
|
118
243
|
optimize : bool
|
|
119
244
|
Improve the minimum scaled Jacobean for each cell. This leads to higher
|
|
120
245
|
cell quality at the expense of computation time.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
246
|
+
simplify : bool, default: True
|
|
247
|
+
Simplfiy the input mesh surface before tetrahedralization.
|
|
248
|
+
epsilon : float, default 1e-3
|
|
249
|
+
Envelop size, specifying the maximum distance of the output surface
|
|
250
|
+
from the input surface, relative to the bounding box size.
|
|
251
|
+
stop_energy : float, default: 10.0
|
|
252
|
+
The mesh optimization stops when the conformal AMIPS energy reaches
|
|
253
|
+
``stop_energy``.
|
|
254
|
+
coarsen : bool, default: False
|
|
255
|
+
Coarsen the output as much as possible, while maintaining the mesh
|
|
256
|
+
quality.
|
|
257
|
+
num_threads : int, default: 0
|
|
258
|
+
Set number of threads used. 0 (default) uses all available cores.
|
|
259
|
+
num_opt_iter : int, default: 80
|
|
260
|
+
Maximum number of optimization iterations if ``optimize=True``.
|
|
261
|
+
loglevel : int, default: 6
|
|
262
|
+
Set log level (0 = most verbose, 6 = minimal output).
|
|
263
|
+
quiet : bool, default: False
|
|
264
|
+
Disable all output. Overrides ``loglevel``.
|
|
265
|
+
vtk_ordering : bool, default: False
|
|
266
|
+
Reorder the tetrahedral cell indices to match VTK's ordering.
|
|
124
267
|
|
|
125
268
|
Returns
|
|
126
269
|
-------
|
|
@@ -133,8 +276,32 @@ def tetrahedralize(
|
|
|
133
276
|
if not isinstance(faces, np.ndarray):
|
|
134
277
|
raise TypeError("`faces` must be a numpy array")
|
|
135
278
|
vertices = vertices.astype(np.float64, copy=False)
|
|
136
|
-
faces
|
|
137
|
-
|
|
279
|
+
if faces.dtype == np.int32:
|
|
280
|
+
# we can cheat here and just treat it as unsigned 32 (assuming no negative indices)
|
|
281
|
+
faces_unsigned = faces.view(np.uint32)
|
|
282
|
+
else:
|
|
283
|
+
faces_unsigned = faces.astype(np.uint32, copy=False)
|
|
284
|
+
|
|
285
|
+
if edge_length_abs is None:
|
|
286
|
+
edge_length_abs = 0.0
|
|
287
|
+
|
|
288
|
+
skip_simplify = not simplify
|
|
289
|
+
return PyfTetWildWrapper.tetrahedralize_mesh(
|
|
290
|
+
vertices,
|
|
291
|
+
faces_unsigned,
|
|
292
|
+
optimize,
|
|
293
|
+
skip_simplify,
|
|
294
|
+
edge_length_fac,
|
|
295
|
+
edge_length_abs,
|
|
296
|
+
epsilon,
|
|
297
|
+
stop_energy,
|
|
298
|
+
coarsen,
|
|
299
|
+
num_threads,
|
|
300
|
+
num_opt_iter,
|
|
301
|
+
loglevel,
|
|
302
|
+
quiet,
|
|
303
|
+
vtk_ordering,
|
|
304
|
+
)
|
|
138
305
|
|
|
139
306
|
|
|
140
307
|
def tetrahedralize_csg(
|
|
@@ -143,6 +310,8 @@ def tetrahedralize_csg(
|
|
|
143
310
|
edge_length_r: float = 0.05,
|
|
144
311
|
stop_energy: float = 10.0,
|
|
145
312
|
coarsen: bool = True,
|
|
313
|
+
num_threads: int = 0,
|
|
314
|
+
loglevel: int = 3,
|
|
146
315
|
) -> "pv.UnstructuredGrid":
|
|
147
316
|
"""
|
|
148
317
|
Generate a tetrahedral mesh based on a the CSG tree specified in the csf_file.
|
|
@@ -152,39 +321,45 @@ def tetrahedralize_csg(
|
|
|
152
321
|
csg_file : str
|
|
153
322
|
Path to the input json file.
|
|
154
323
|
epsilon : float, default 1e-3
|
|
155
|
-
Envelop size, specifying the maximum distance of the output surface
|
|
156
|
-
relative to the bounding box size.
|
|
324
|
+
Envelop size, specifying the maximum distance of the output surface
|
|
325
|
+
from the input surface, relative to the bounding box size.
|
|
157
326
|
edge_length_r : float, default: 0.05
|
|
158
|
-
Tetrahedral edge length as a function of bounding box
|
|
327
|
+
Tetrahedral edge length as a function of bounding box diagonal. The
|
|
159
328
|
default ideal edge length is bb/20 (bounding box divided by 20).
|
|
160
329
|
stop_energy : float, default: 10.0
|
|
161
330
|
The mesh optimization stops when the conformal AMIPS energy reaches 'stop_energy'.
|
|
162
331
|
coarsen : bool, default: true
|
|
163
|
-
|
|
332
|
+
Coarsen the output as much as possible, while maintaining the mesh quality.
|
|
333
|
+
num_threads : int, default: 0
|
|
334
|
+
Set number of threads used (0 means all available cores).
|
|
335
|
+
loglevel : int, default: 6
|
|
336
|
+
Set log level (0 = most verbose, 6 = minimal output).
|
|
164
337
|
|
|
165
338
|
Returns
|
|
166
339
|
-------
|
|
167
340
|
pv.UnstructuredGrid
|
|
168
|
-
The converted unstructured grid containing only tetrahedra,
|
|
169
|
-
|
|
341
|
+
The converted unstructured grid containing only tetrahedra, with a cell
|
|
342
|
+
attribute 'marker' indicating which of the input surfaces the cell
|
|
343
|
+
belongs to.
|
|
170
344
|
"""
|
|
171
345
|
try:
|
|
172
|
-
|
|
346
|
+
pass
|
|
173
347
|
except:
|
|
174
348
|
raise ModuleNotFoundError(
|
|
175
349
|
"Install PyVista to use this feature with:\n\npip install pytetwild[all]"
|
|
176
350
|
)
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
351
|
+
vtk_ordering = True
|
|
352
|
+
tmesh_v, tmesh_c, tmesh_marker = PyfTetWildWrapper.tetrahedralize_csg(
|
|
353
|
+
csg_file,
|
|
354
|
+
epsilon,
|
|
355
|
+
edge_length_r,
|
|
356
|
+
stop_energy,
|
|
357
|
+
coarsen,
|
|
358
|
+
num_threads,
|
|
359
|
+
loglevel,
|
|
360
|
+
vtk_ordering,
|
|
185
361
|
)
|
|
186
|
-
cell_types = np.full(tetrahedral_mesh_tetrahedra.shape[0], 10, dtype=np.uint8)
|
|
187
362
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
return
|
|
363
|
+
ugrid = _ugrid_from_regular_cells(tmesh_v, tmesh_c).clean()
|
|
364
|
+
ugrid["marker"] = tmesh_marker
|
|
365
|
+
return ugrid
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Version: 1.12.0
|
|
2
|
+
Arguments: ['C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-df7o4pf6\\cp310-win_amd64\\build\\venv\\Scripts\\delvewheel', 'repair', '-w', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-df7o4pf6\\cp310-win_amd64\\repaired_wheel', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-df7o4pf6\\cp310-win_amd64\\built_wheel\\pytetwild-0.2.2-cp310-cp310-win_amd64.whl', '--add-path', '.']
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: pytetwild
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Python wrapper of fTetWild
|
|
5
5
|
Author-Email: Alex Kaszynski <akascap@gmail.com>
|
|
6
6
|
Classifier: Development Status :: 3 - Alpha
|
|
@@ -10,20 +10,22 @@ Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
|
|
|
10
10
|
Classifier: Operating System :: Microsoft :: Windows
|
|
11
11
|
Classifier: Operating System :: POSIX
|
|
12
12
|
Classifier: Operating System :: MacOS
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
15
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
14
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
15
|
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Requires-Python: <3.15,>=3.10
|
|
18
19
|
Requires-Dist: numpy
|
|
19
20
|
Provides-Extra: all
|
|
20
21
|
Requires-Dist: pyvista; extra == "all"
|
|
22
|
+
Provides-Extra: tests
|
|
23
|
+
Requires-Dist: pytest; extra == "tests"
|
|
24
|
+
Requires-Dist: pyvista; extra == "tests"
|
|
25
|
+
Requires-Dist: scipy<1.17.0; extra == "tests"
|
|
26
|
+
Requires-Dist: meshio; extra == "tests"
|
|
21
27
|
Provides-Extra: dev
|
|
22
|
-
Requires-Dist: pytest; extra == "dev"
|
|
23
28
|
Requires-Dist: pre-commit; extra == "dev"
|
|
24
|
-
Requires-Dist: pyvista; extra == "dev"
|
|
25
|
-
Requires-Dist: scipy; extra == "dev"
|
|
26
|
-
Requires-Dist: meshio; extra == "dev"
|
|
27
29
|
Description-Content-Type: text/x-rst
|
|
28
30
|
|
|
29
31
|
pytetwild
|
|
@@ -45,13 +47,17 @@ Python wrapper around the efficient C++ library for tetrahedral meshing provided
|
|
|
45
47
|
Installation
|
|
46
48
|
************
|
|
47
49
|
|
|
48
|
-
We have pre-built wheels for Python 3.
|
|
50
|
+
We have pre-built wheels for Python 3.10 - Python 3.14 for Windows, Linux, and macOS.
|
|
49
51
|
|
|
50
52
|
The recommended way to install ``pytetwild`` is via PyPI:
|
|
51
53
|
|
|
52
54
|
.. code:: sh
|
|
53
55
|
|
|
54
|
-
pip install pytetwild
|
|
56
|
+
pip install pytetwild[all]
|
|
57
|
+
|
|
58
|
+
This installs ``pyvista`` by default, which you can use to tetrahedralize
|
|
59
|
+
sufrace meshes from PyVista. Alternatively you can just install with ``pip
|
|
60
|
+
install pytetwild`` for a lighter install.
|
|
55
61
|
|
|
56
62
|
You can also clone the repository and install it from source, but since there's
|
|
57
63
|
C++ involved, the build is a bit more complicated. See ``CONTRIBUTING.md`` for
|
|
@@ -61,7 +67,8 @@ more details.
|
|
|
61
67
|
Usage
|
|
62
68
|
*****
|
|
63
69
|
|
|
64
|
-
To tetrahedralize a surface mesh from `PyVista <https://docs.pyvista.org>`_
|
|
70
|
+
To tetrahedralize a surface mesh from `PyVista <https://docs.pyvista.org>`_,
|
|
71
|
+
you'll need to first install ``pyvista`` as it's not a dependency and then run:
|
|
65
72
|
|
|
66
73
|
.. code:: py
|
|
67
74
|
|
|
@@ -77,15 +84,19 @@ To tetrahedralize a surface mesh from `PyVista <https://docs.pyvista.org>`_:
|
|
|
77
84
|
tetrahedral_mesh = pytetwild.tetrahedralize_pv(surface_mesh, edge_length_fac=1)
|
|
78
85
|
|
|
79
86
|
# Visualize the tetrahedral mesh in an "exploded" view
|
|
80
|
-
tetrahedral_mesh.explode(
|
|
87
|
+
tetrahedral_mesh.explode(0.5).plot(
|
|
88
|
+
show_edges=True, zoom=1.6, ssao=True, anti_aliasing="ssaa"
|
|
89
|
+
)
|
|
90
|
+
|
|
81
91
|
|
|
82
92
|
.. image:: https://github.com/pyvista/pytetwild/raw/main/exploded-sphere.png
|
|
83
93
|
|
|
84
94
|
You can also work with raw arrays. Here's a simple cube that we turn into tetrahedra.
|
|
85
95
|
|
|
86
|
-
.. code::
|
|
96
|
+
.. code:: py
|
|
87
97
|
|
|
88
98
|
import numpy as np
|
|
99
|
+
import pytetwild
|
|
89
100
|
|
|
90
101
|
# Define vertices of the cube
|
|
91
102
|
vertices = np.array([
|
|
@@ -114,25 +125,49 @@ You can also work with raw arrays. Here's a simple cube that we turn into tetrah
|
|
|
114
125
|
|
|
115
126
|
Usage - Options
|
|
116
127
|
---------------
|
|
117
|
-
We've surfaced a
|
|
118
|
-
``tetrahedralize`` and ``tetrahedralize_pv
|
|
128
|
+
We've surfaced a several parameters to each of our interfaces
|
|
129
|
+
``tetrahedralize`` and ``tetrahedralize_pv``:
|
|
119
130
|
|
|
120
131
|
.. code::
|
|
121
132
|
|
|
122
|
-
|
|
123
|
-
|
|
133
|
+
Parameters
|
|
134
|
+
----------
|
|
124
135
|
edge_length_fac : float, default: 0.05
|
|
125
136
|
Tetrahedral edge length as a function of bounding box diagonal. The
|
|
126
|
-
default ideal edge length is bb/20 (bounding box divided by
|
|
127
|
-
|
|
137
|
+
default ideal edge length is ``bb/20`` (bounding box divided by
|
|
138
|
+
20). Ignored when ``edge_length_abs`` is input.
|
|
139
|
+
edge_length_abs : float, optional
|
|
140
|
+
Absolute ideal edge length. When input ``edge_length_fac`` is ignored.
|
|
141
|
+
optimize : bool, default: True
|
|
128
142
|
Improve the minimum scaled Jacobean for each cell. This leads to higher
|
|
129
|
-
cell quality at the expense of computation time.
|
|
143
|
+
cell quality at the expense of computation time. Optimization level is
|
|
144
|
+
dependent on ``stop_energy`` and ``num_opt_iter``.
|
|
145
|
+
simplify : bool, default: True
|
|
146
|
+
Simplfiy the input mesh surface before tetrahedralization.
|
|
147
|
+
epsilon : float, default 1e-3
|
|
148
|
+
Envelop size, specifying the maximum distance of the output surface
|
|
149
|
+
from the input surface, relative to the bounding box size.
|
|
150
|
+
stop_energy : float, default: 10.0
|
|
151
|
+
The mesh optimization stops when the conformal AMIPS energy reaches
|
|
152
|
+
``stop_energy``.
|
|
153
|
+
coarsen : bool, default: False
|
|
154
|
+
Coarsen the output as much as possible, while maintaining the mesh
|
|
155
|
+
quality.
|
|
156
|
+
num_threads : int, default: 0
|
|
157
|
+
Set number of threads used. 0 (default) uses all available cores.
|
|
158
|
+
num_opt_iter : int, default: 80
|
|
159
|
+
Maximum number of optimization iterations if ``optimize=True``.
|
|
160
|
+
loglevel : int, default: 6
|
|
161
|
+
Set log level (0 = most verbose, 6 = minimal output).
|
|
162
|
+
quiet : bool, default: False
|
|
163
|
+
Disable all output. Overrides ``loglevel``.
|
|
164
|
+
|
|
130
165
|
|
|
131
166
|
|
|
132
167
|
License and Acknowledgments
|
|
133
168
|
***************************
|
|
134
169
|
|
|
135
|
-
This project relies on ``fTetWild`` and
|
|
170
|
+
This project relies on ``fTetWild`` and credit goes to the original authors for
|
|
136
171
|
their efficient C++ library for tetrahedral meshing. That work is licensed
|
|
137
172
|
under the Mozilla Public License v2.0.
|
|
138
173
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
pytetwild/py.typed,sha256=mDShSrm8qg9qjacQc2F-rI8ATllqP6EdgHuEYxuCXZ0,7
|
|
2
|
+
pytetwild/PyfTetWildWrapper.pyd,sha256=3Pz0Ihjxpm8FWtx8yXcuhjVQcMYqKBGKlk3Qk1ixsR8,5899264
|
|
3
|
+
pytetwild/PyfTetWildWrapper.pyi,sha256=hNiPnsN-o1-EGSzDeP2lkKEx9zTwrVQVYQFHunueDOY,769
|
|
4
|
+
pytetwild/pytetwild.py,sha256=dyz-HMQCFccv1Db1AXubG24iNRkFyFMY-8xvyLm7WwA,12601
|
|
5
|
+
pytetwild/_version.py,sha256=A4_1DWpVQi-Rp5-lH3Itz0MNxg-VoQh0v0s0Wub4PQ4,120
|
|
6
|
+
pytetwild/__init__.py,sha256=Ccsw00SOCxDfe-SfqiHy-D0QZohTB9kD0LMe4GgVHKY,498
|
|
7
|
+
pytetwild-0.2.2.dist-info/DELVEWHEEL,sha256=F8_yua3RFoJ4rwOui6_p6Y8cAKoqLZh5pdGavdNZBM8,421
|
|
8
|
+
pytetwild-0.2.2.dist-info/METADATA,sha256=243SaU64Vua7K4_9MepVW5QLtV_snyMa_SCEKrqv1bM,6138
|
|
9
|
+
pytetwild-0.2.2.dist-info/RECORD,,
|
|
10
|
+
pytetwild-0.2.2.dist-info/WHEEL,sha256=hrGeChGtn46HBGmzasO9QQDSLelRN-tUarBSv4gFcsI,106
|
|
11
|
+
pytetwild-0.2.2.dist-info/licenses/LICENSE,sha256=k0P1sbYupRWlxoESvbYq2UzoMW6MXA84LltqR-4mEo4,17096
|
|
12
|
+
pytetwild.libs/concrt140-63a42d2def1023b22584817146cee33d.dll,sha256=tWTNrcqIbCkALGnMNEoKRuaSbXscOIw0F5gWYZzfmDY,304128
|
|
13
|
+
pytetwild.libs/mpir-68915c4420c2a122a0aba56cd715bd26.dll,sha256=96pOmyi8-b4gAyXakkz7w0arxMoDHxmlAU33OZXMKAY,612352
|
|
14
|
+
pytetwild.libs/msvcp140-8f141b4454fa78db34bc1f28c571b4da.dll,sha256=jxQbRFT6eNs0vB8oxXG02g4AzSxD960OKC8xMDaCaq4,557648
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
Version: 1.11.1
|
|
2
|
-
Arguments: ['C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-abil8mqp\\cp310-win_amd64\\build\\venv\\Scripts\\delvewheel', 'repair', '-w', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-abil8mqp\\cp310-win_amd64\\repaired_wheel', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-abil8mqp\\cp310-win_amd64\\built_wheel\\pytetwild-0.1.0-cp310-cp310-win_amd64.whl', '--add-path', '.']
|
pytetwild-0.1.0.dist-info/RECORD
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
pytetwild/py.typed,sha256=mDShSrm8qg9qjacQc2F-rI8ATllqP6EdgHuEYxuCXZ0,7
|
|
2
|
-
pytetwild/PyfTetWildWrapper.pyd,sha256=dOSMuUOf1i0kCfBMxNoLTMl4QriU32c4uGShvF1vnOc,5930496
|
|
3
|
-
pytetwild/pytetwild.py,sha256=yy0bCZHMDyouDYKN5siWoYglTxEuF4kIRiloi8YARfc,6666
|
|
4
|
-
pytetwild/_version.py,sha256=A4_1DWpVQi-Rp5-lH3Itz0MNxg-VoQh0v0s0Wub4PQ4,120
|
|
5
|
-
pytetwild/__init__.py,sha256=mAKKFh6ft1IQP8YeXqMvgq0Dvwe92BlmD2FpjaMB9cU,498
|
|
6
|
-
pytetwild-0.1.0.dist-info/DELVEWHEEL,sha256=hsbjXR87ls5liJpC6NbmH6UqRiJZqr28ZQPYoNCnauA,421
|
|
7
|
-
pytetwild-0.1.0.dist-info/METADATA,sha256=B9R69fA69cvI8kNeALJTohpme9msRA_EWsLB6H4A6E0,4560
|
|
8
|
-
pytetwild-0.1.0.dist-info/RECORD,,
|
|
9
|
-
pytetwild-0.1.0.dist-info/WHEEL,sha256=hrGeChGtn46HBGmzasO9QQDSLelRN-tUarBSv4gFcsI,106
|
|
10
|
-
pytetwild-0.1.0.dist-info/licenses/LICENSE,sha256=k0P1sbYupRWlxoESvbYq2UzoMW6MXA84LltqR-4mEo4,17096
|
|
11
|
-
pytetwild.libs/concrt140-63a42d2def1023b22584817146cee33d.dll,sha256=tWTNrcqIbCkALGnMNEoKRuaSbXscOIw0F5gWYZzfmDY,304128
|
|
12
|
-
pytetwild.libs/mpir-68915c4420c2a122a0aba56cd715bd26.dll,sha256=96pOmyi8-b4gAyXakkz7w0arxMoDHxmlAU33OZXMKAY,612352
|
|
13
|
-
pytetwild.libs/msvcp140-8f141b4454fa78db34bc1f28c571b4da.dll,sha256=jxQbRFT6eNs0vB8oxXG02g4AzSxD960OKC8xMDaCaq4,557648
|
|
File without changes
|
|
File without changes
|