pytetwild 0.1.dev1__cp310-cp310-win_amd64.whl → 0.2.0__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 +5 -6
- pytetwild/_version.py +1 -0
- pytetwild/pytetwild.py +270 -41
- pytetwild-0.2.0.dist-info/DELVEWHEEL +2 -0
- {pytetwild-0.1.dev1.dist-info → pytetwild-0.2.0.dist-info}/METADATA +60 -26
- pytetwild-0.2.0.dist-info/RECORD +14 -0
- {pytetwild-0.1.dev1.dist-info → pytetwild-0.2.0.dist-info}/WHEEL +1 -1
- pytetwild.libs/concrt140-63a42d2def1023b22584817146cee33d.dll +0 -0
- pytetwild.libs/{mpir-0f58ffaa159ebf7efb9359a55c2d7f23.dll → mpir-68915c4420c2a122a0aba56cd715bd26.dll} +0 -0
- pytetwild.libs/msvcp140-8f141b4454fa78db34bc1f28c571b4da.dll +0 -0
- pytetwild-0.1.dev1.dist-info/DELVEWHEEL +0 -2
- pytetwild-0.1.dev1.dist-info/RECORD +0 -14
- pytetwild-0.1.dev1.dist-info/entry_points.txt +0 -0
- pytetwild.libs/concrt140-ddbfd8b75976783430ced289c6b989c3.dll +0 -0
- pytetwild.libs/msvcp140-3499a3a8427eec4915749ee9a8991ddd.dll +0 -0
- {pytetwild-0.1.dev1.dist-info → pytetwild-0.2.0.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,16 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
# start delvewheel patch
|
|
5
|
-
def
|
|
5
|
+
def _delvewheel_patch_1_12_0():
|
|
6
6
|
import os
|
|
7
|
-
libs_dir
|
|
8
|
-
if os.path.isdir(libs_dir):
|
|
7
|
+
if os.path.isdir(libs_dir := os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir, 'pytetwild.libs'))):
|
|
9
8
|
os.add_dll_directory(libs_dir)
|
|
10
9
|
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
del
|
|
11
|
+
_delvewheel_patch_1_12_0()
|
|
12
|
+
del _delvewheel_patch_1_12_0
|
|
14
13
|
# end delvewheel patch
|
|
15
14
|
|
|
16
15
|
from ._version import __version__ # noqa: F401
|
|
17
|
-
from .pytetwild import tetrahedralize, tetrahedralize_pv # noqa: F401
|
|
16
|
+
from .pytetwild import tetrahedralize, tetrahedralize_pv, tetrahedralize_csg # noqa: F401
|
pytetwild/_version.py
CHANGED
pytetwild/pytetwild.py
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
"""Wrapper for fTetWild."""
|
|
2
|
+
|
|
2
3
|
import warnings
|
|
3
4
|
import numpy as np
|
|
4
|
-
from pytetwild import PyfTetWildWrapper
|
|
5
|
-
from typing import
|
|
6
|
-
|
|
5
|
+
from pytetwild import PyfTetWildWrapper
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
|
+
from numpy.typing import NDArray
|
|
7
8
|
|
|
8
9
|
if TYPE_CHECKING:
|
|
9
10
|
import pyvista as pv
|
|
10
11
|
|
|
12
|
+
VTK_UNSIGNED_CHAR = 3
|
|
13
|
+
VTK_TETRA = 10
|
|
14
|
+
VTK_QUADRATIC_TETRA = 24
|
|
15
|
+
|
|
11
16
|
|
|
12
17
|
def _check_edge_length(edge_length_fac: float) -> None:
|
|
13
18
|
"""Check edge length.
|
|
@@ -15,17 +20,87 @@ def _check_edge_length(edge_length_fac: float) -> None:
|
|
|
15
20
|
Parameters
|
|
16
21
|
----------
|
|
17
22
|
edge_length_fac : float, default: 0.05
|
|
18
|
-
Tetrahedral edge length as a function of bounding box
|
|
23
|
+
Tetrahedral edge length as a function of bounding box diagonal. The
|
|
19
24
|
default ideal edge length is bb/20 (bounding box divided by 20).
|
|
20
25
|
|
|
21
|
-
|
|
22
26
|
"""
|
|
23
27
|
if edge_length_fac > 1.0 or edge_length_fac < 0.0 + 1e-16:
|
|
24
28
|
raise ValueError("Edge length factor must be between 1e-16 and 1.0")
|
|
25
29
|
|
|
26
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
|
+
|
|
27
91
|
def tetrahedralize_pv(
|
|
28
|
-
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,
|
|
29
104
|
) -> "pv.UnstructuredGrid":
|
|
30
105
|
"""
|
|
31
106
|
Convert a PyVista surface mesh to a PyVista unstructured grid.
|
|
@@ -33,13 +108,36 @@ def tetrahedralize_pv(
|
|
|
33
108
|
Parameters
|
|
34
109
|
----------
|
|
35
110
|
mesh : pv.PolyData
|
|
36
|
-
The input surface mesh.
|
|
111
|
+
The input surface mesh. Should be composed of all triangles.
|
|
37
112
|
edge_length_fac : float, default: 0.05
|
|
38
|
-
Tetrahedral edge length as a function of bounding box
|
|
39
|
-
default ideal edge length is bb/20 (bounding box divided by
|
|
40
|
-
|
|
113
|
+
Tetrahedral edge length as a function of bounding box diagonal. The
|
|
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
|
|
41
119
|
Improve the minimum scaled Jacobean for each cell. This leads to higher
|
|
42
|
-
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``.
|
|
43
141
|
|
|
44
142
|
Returns
|
|
45
143
|
-------
|
|
@@ -63,63 +161,109 @@ def tetrahedralize_pv(
|
|
|
63
161
|
|
|
64
162
|
"""
|
|
65
163
|
try:
|
|
66
|
-
import pyvista as pv
|
|
164
|
+
import pyvista.core as pv
|
|
67
165
|
except:
|
|
68
166
|
raise ModuleNotFoundError(
|
|
69
|
-
"Install PyVista to use this feature with:\n\
|
|
167
|
+
"Install PyVista to use this feature with:\n\npip install pytetwild[all]"
|
|
70
168
|
)
|
|
71
169
|
|
|
72
170
|
if not isinstance(mesh, pv.PolyData):
|
|
73
171
|
raise TypeError(f"`mesh` must be a pyvista.PolyData, got {type(mesh)}")
|
|
74
|
-
|
|
75
172
|
if not mesh.is_all_triangles:
|
|
76
173
|
warnings.warn(
|
|
77
174
|
"Input mesh is not all triangles. Either call `.triangulate()`"
|
|
78
175
|
" beforehand to suppress this warning or use an all triangle mesh."
|
|
79
176
|
)
|
|
80
177
|
mesh = mesh.triangulate()
|
|
81
|
-
|
|
82
178
|
_check_edge_length(edge_length_fac)
|
|
179
|
+
|
|
180
|
+
if edge_length_abs is None:
|
|
181
|
+
edge_length_abs = 0.0
|
|
182
|
+
|
|
83
183
|
vertices = mesh.points.astype(np.float64, copy=False)
|
|
84
|
-
faces = mesh.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
cells = np.hstack(
|
|
92
|
-
[
|
|
93
|
-
np.full((tetrahedral_mesh_tetrahedra.shape[0], 1), 4, dtype=np.int32),
|
|
94
|
-
tetrahedral_mesh_tetrahedra,
|
|
95
|
-
]
|
|
96
|
-
)
|
|
97
|
-
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)
|
|
98
190
|
|
|
99
|
-
|
|
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)
|
|
100
210
|
|
|
101
211
|
|
|
102
212
|
def tetrahedralize(
|
|
103
|
-
vertices:
|
|
104
|
-
faces:
|
|
105
|
-
optimize: bool = True,
|
|
213
|
+
vertices: NDArray[np.float32] | NDArray[np.float64],
|
|
214
|
+
faces: NDArray[np.int32],
|
|
106
215
|
edge_length_fac: float = 0.05,
|
|
107
|
-
|
|
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]]:
|
|
108
228
|
"""
|
|
109
229
|
Convert mesh vertices and faces to a tetrahedral mesh.
|
|
110
230
|
|
|
111
231
|
Parameters
|
|
112
232
|
----------
|
|
113
|
-
vertices : np.ndarray[
|
|
233
|
+
vertices : np.ndarray[np.float32] | np.ndarray[np.float64]
|
|
114
234
|
The vertices of the mesh.
|
|
115
|
-
faces : np.ndarray
|
|
235
|
+
faces : np.ndarray[np.int32]
|
|
116
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.
|
|
117
243
|
optimize : bool
|
|
118
244
|
Improve the minimum scaled Jacobean for each cell. This leads to higher
|
|
119
245
|
cell quality at the expense of computation time.
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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.
|
|
123
267
|
|
|
124
268
|
Returns
|
|
125
269
|
-------
|
|
@@ -132,5 +276,90 @@ def tetrahedralize(
|
|
|
132
276
|
if not isinstance(faces, np.ndarray):
|
|
133
277
|
raise TypeError("`faces` must be a numpy array")
|
|
134
278
|
vertices = vertices.astype(np.float64, copy=False)
|
|
135
|
-
faces
|
|
136
|
-
|
|
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
|
+
)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def tetrahedralize_csg(
|
|
308
|
+
csg_file: str,
|
|
309
|
+
epsilon: float = 1e-3,
|
|
310
|
+
edge_length_r: float = 0.05,
|
|
311
|
+
stop_energy: float = 10.0,
|
|
312
|
+
coarsen: bool = True,
|
|
313
|
+
num_threads: int = 0,
|
|
314
|
+
loglevel: int = 3,
|
|
315
|
+
) -> "pv.UnstructuredGrid":
|
|
316
|
+
"""
|
|
317
|
+
Generate a tetrahedral mesh based on a the CSG tree specified in the csf_file.
|
|
318
|
+
|
|
319
|
+
Parameters
|
|
320
|
+
----------
|
|
321
|
+
csg_file : str
|
|
322
|
+
Path to the input json file.
|
|
323
|
+
epsilon : float, default 1e-3
|
|
324
|
+
Envelop size, specifying the maximum distance of the output surface
|
|
325
|
+
from the input surface, relative to the bounding box size.
|
|
326
|
+
edge_length_r : float, default: 0.05
|
|
327
|
+
Tetrahedral edge length as a function of bounding box diagonal. The
|
|
328
|
+
default ideal edge length is bb/20 (bounding box divided by 20).
|
|
329
|
+
stop_energy : float, default: 10.0
|
|
330
|
+
The mesh optimization stops when the conformal AMIPS energy reaches 'stop_energy'.
|
|
331
|
+
coarsen : bool, default: true
|
|
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).
|
|
337
|
+
|
|
338
|
+
Returns
|
|
339
|
+
-------
|
|
340
|
+
pv.UnstructuredGrid
|
|
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.
|
|
344
|
+
"""
|
|
345
|
+
try:
|
|
346
|
+
pass
|
|
347
|
+
except:
|
|
348
|
+
raise ModuleNotFoundError(
|
|
349
|
+
"Install PyVista to use this feature with:\n\npip install pytetwild[all]"
|
|
350
|
+
)
|
|
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,
|
|
361
|
+
)
|
|
362
|
+
|
|
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-qrk3shix\\cp310-win_amd64\\build\\venv\\Scripts\\delvewheel', 'repair', '-w', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-qrk3shix\\cp310-win_amd64\\repaired_wheel', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-qrk3shix\\cp310-win_amd64\\built_wheel\\pytetwild-0.2.0-cp310-cp310-win_amd64.whl', '--add-path', '.']
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: pytetwild
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Python wrapper of fTetWild
|
|
5
5
|
Author-Email: Alex Kaszynski <akascap@gmail.com>
|
|
6
6
|
Classifier: Development Status :: 3 - Alpha
|
|
@@ -10,22 +10,23 @@ 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
|
-
Requires-Dist: pyvista; extra == "all"
|
|
20
|
-
Requires-Dist: pytest; extra == "dev"
|
|
21
|
-
Requires-Dist: pre-commit; extra == "dev"
|
|
22
|
-
Requires-Dist: pyvista; extra == "dev"
|
|
23
|
-
Requires-Dist: scipy; extra == "dev"
|
|
24
|
-
Requires-Dist: meshio; extra == "dev"
|
|
25
20
|
Provides-Extra: all
|
|
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; extra == "tests"
|
|
26
|
+
Requires-Dist: meshio; extra == "tests"
|
|
26
27
|
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pre-commit; extra == "dev"
|
|
27
29
|
Description-Content-Type: text/x-rst
|
|
28
|
-
License-File: LICENSE
|
|
29
30
|
|
|
30
31
|
pytetwild
|
|
31
32
|
#########
|
|
@@ -46,13 +47,17 @@ Python wrapper around the efficient C++ library for tetrahedral meshing provided
|
|
|
46
47
|
Installation
|
|
47
48
|
************
|
|
48
49
|
|
|
49
|
-
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.
|
|
50
51
|
|
|
51
52
|
The recommended way to install ``pytetwild`` is via PyPI:
|
|
52
53
|
|
|
53
54
|
.. code:: sh
|
|
54
55
|
|
|
55
|
-
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.
|
|
56
61
|
|
|
57
62
|
You can also clone the repository and install it from source, but since there's
|
|
58
63
|
C++ involved, the build is a bit more complicated. See ``CONTRIBUTING.md`` for
|
|
@@ -62,7 +67,8 @@ more details.
|
|
|
62
67
|
Usage
|
|
63
68
|
*****
|
|
64
69
|
|
|
65
|
-
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:
|
|
66
72
|
|
|
67
73
|
.. code:: py
|
|
68
74
|
|
|
@@ -75,18 +81,22 @@ To tetrahedralize a surface mesh from `PyVista <https://docs.pyvista.org>`_:
|
|
|
75
81
|
|
|
76
82
|
# Convert the surface mesh to a tetrahedral mesh. For this example let's
|
|
77
83
|
# use a coarse mesh
|
|
78
|
-
tetrahedral_mesh = pytetwild.tetrahedralize_pv(surface_mesh, edge_length_fac=1)
|
|
84
|
+
tetrahedral_mesh = pytetwild.tetrahedralize_pv(surface_mesh, edge_length_fac=1)
|
|
79
85
|
|
|
80
86
|
# Visualize the tetrahedral mesh in an "exploded" view
|
|
81
|
-
tetrahedral_mesh.explode(
|
|
87
|
+
tetrahedral_mesh.explode(0.5).plot(
|
|
88
|
+
show_edges=True, zoom=1.6, ssao=True, anti_aliasing="ssaa"
|
|
89
|
+
)
|
|
90
|
+
|
|
82
91
|
|
|
83
92
|
.. image:: https://github.com/pyvista/pytetwild/raw/main/exploded-sphere.png
|
|
84
93
|
|
|
85
94
|
You can also work with raw arrays. Here's a simple cube that we turn into tetrahedra.
|
|
86
95
|
|
|
87
|
-
.. code::
|
|
96
|
+
.. code:: py
|
|
88
97
|
|
|
89
98
|
import numpy as np
|
|
99
|
+
import pytetwild
|
|
90
100
|
|
|
91
101
|
# Define vertices of the cube
|
|
92
102
|
vertices = np.array([
|
|
@@ -115,25 +125,49 @@ You can also work with raw arrays. Here's a simple cube that we turn into tetrah
|
|
|
115
125
|
|
|
116
126
|
Usage - Options
|
|
117
127
|
---------------
|
|
118
|
-
We've surfaced a
|
|
119
|
-
``tetrahedralize`` and ``tetrahedralize_pv
|
|
128
|
+
We've surfaced a several parameters to each of our interfaces
|
|
129
|
+
``tetrahedralize`` and ``tetrahedralize_pv``:
|
|
120
130
|
|
|
121
131
|
.. code::
|
|
122
132
|
|
|
123
|
-
|
|
124
|
-
|
|
133
|
+
Parameters
|
|
134
|
+
----------
|
|
125
135
|
edge_length_fac : float, default: 0.05
|
|
126
|
-
Tetrahedral edge length as a function of bounding box
|
|
127
|
-
default ideal edge length is bb/20 (bounding box divided by
|
|
128
|
-
|
|
136
|
+
Tetrahedral edge length as a function of bounding box diagonal. The
|
|
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
|
|
129
142
|
Improve the minimum scaled Jacobean for each cell. This leads to higher
|
|
130
|
-
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
|
+
|
|
131
165
|
|
|
132
166
|
|
|
133
167
|
License and Acknowledgments
|
|
134
168
|
***************************
|
|
135
169
|
|
|
136
|
-
This project relies on ``fTetWild`` and
|
|
170
|
+
This project relies on ``fTetWild`` and credit goes to the original authors for
|
|
137
171
|
their efficient C++ library for tetrahedral meshing. That work is licensed
|
|
138
172
|
under the Mozilla Public License v2.0.
|
|
139
173
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
pytetwild/py.typed,sha256=mDShSrm8qg9qjacQc2F-rI8ATllqP6EdgHuEYxuCXZ0,7
|
|
2
|
+
pytetwild/PyfTetWildWrapper.pyd,sha256=0ON5fI5JN4Reh2qwH0pElTg4qdV3bECFoprNkYGt08k,5898752
|
|
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.0.dist-info/DELVEWHEEL,sha256=xvA-7Mn7KlqJuS6aCe-pv-0FLGP-Ex4f-BUHgYbZ_as,421
|
|
8
|
+
pytetwild-0.2.0.dist-info/METADATA,sha256=W2TWaKZlnSapb1l0vwV4nvbPQNiaPd76VdoaEm1hdFI,6131
|
|
9
|
+
pytetwild-0.2.0.dist-info/RECORD,,
|
|
10
|
+
pytetwild-0.2.0.dist-info/WHEEL,sha256=hrGeChGtn46HBGmzasO9QQDSLelRN-tUarBSv4gFcsI,106
|
|
11
|
+
pytetwild-0.2.0.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
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
Version: 1.5.4
|
|
2
|
-
Arguments: ['C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-rdukv1yg\\cp310-win_amd64\\build\\venv\\Scripts\\delvewheel', 'repair', '-w', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-rdukv1yg\\cp310-win_amd64\\repaired_wheel', 'C:\\Users\\runneradmin\\AppData\\Local\\Temp\\cibw-run-rdukv1yg\\cp310-win_amd64\\built_wheel\\pytetwild-0.1.dev1-cp310-cp310-win_amd64.whl', '--add-path', '.']
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
pytetwild/py.typed,sha256=mDShSrm8qg9qjacQc2F-rI8ATllqP6EdgHuEYxuCXZ0,7
|
|
2
|
-
pytetwild/PyfTetWildWrapper.pyd,sha256=drheVC_9LDlGgYPyjAdcxmEKW0Rcsu2wNx2xOBrZFVs,4988416
|
|
3
|
-
pytetwild/pytetwild.py,sha256=PSLlG5czLo2Z2aZtcgxmZAy97E9eAtbo7EdvY0WONIs,4646
|
|
4
|
-
pytetwild/_version.py,sha256=hbg9UkagWDGV6Zg23kEpex_otuUYHUzMCHXYTnFnHmE,118
|
|
5
|
-
pytetwild/__init__.py,sha256=QdK3GINbrnK1cwEauX0cPgzkVCa1VPait8aGT2AJN4Q,486
|
|
6
|
-
pytetwild-0.1.dev1.dist-info/DELVEWHEEL,sha256=9gdhJR4vb_YdBPE6ej5YzI4lvi6480X3Wh0PPcfM5TM,423
|
|
7
|
-
pytetwild-0.1.dev1.dist-info/entry_points.txt,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
pytetwild-0.1.dev1.dist-info/METADATA,sha256=6I1FzXoY9ezDC8EWamtUR2MVxWtBvgjD5frhxz4gw6Y,4587
|
|
9
|
-
pytetwild-0.1.dev1.dist-info/RECORD,,
|
|
10
|
-
pytetwild-0.1.dev1.dist-info/WHEEL,sha256=8XuJkyxPIT13OzegTGarRVhmDP5NkOix_zaC7jtZJJE,105
|
|
11
|
-
pytetwild-0.1.dev1.dist-info/licenses/LICENSE,sha256=k0P1sbYupRWlxoESvbYq2UzoMW6MXA84LltqR-4mEo4,17096
|
|
12
|
-
pytetwild.libs/concrt140-ddbfd8b75976783430ced289c6b989c3.dll,sha256=BZPGv1uz0YBgBOgTWBBL0elt7C3clmR348_2Zlqh47Q,302080
|
|
13
|
-
pytetwild.libs/mpir-0f58ffaa159ebf7efb9359a55c2d7f23.dll,sha256=qd6vEIL0JPtRZ39EzelGE9rApfJ6duoMgV8jT8UHGns,612352
|
|
14
|
-
pytetwild.libs/msvcp140-3499a3a8427eec4915749ee9a8991ddd.dll,sha256=oDDcLf0uyiipN1ySmJrfTa8WH5iNteFrnhBnjrDf9Mc,573008
|
|
File without changes
|
|
Binary file
|
|
Binary file
|
|
File without changes
|