mmgpy 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.
- bin/__init__.py +10 -0
- bin/concrt140.dll +0 -0
- bin/mmg.dll +0 -0
- bin/mmg2d.dll +0 -0
- bin/mmg2d_O3.exe +0 -0
- bin/mmg3d.dll +0 -0
- bin/mmg3d_O3.exe +0 -0
- bin/mmgs.dll +0 -0
- bin/mmgs_O3.exe +0 -0
- bin/msvcp140.dll +0 -0
- bin/msvcp140_1.dll +0 -0
- bin/msvcp140_2.dll +0 -0
- bin/msvcp140_atomic_wait.dll +0 -0
- bin/msvcp140_codecvt_ids.dll +0 -0
- bin/vcruntime140.dll +0 -0
- bin/vcruntime140_1.dll +0 -0
- include/__init__.py +10 -0
- include/mmg/common/libmmgtypes.h +687 -0
- include/mmg/common/libmmgtypesf.h +762 -0
- include/mmg/common/mmg_export.h +47 -0
- include/mmg/common/mmgcmakedefines.h +46 -0
- include/mmg/common/mmgcmakedefinesf.h +29 -0
- include/mmg/common/mmgversion.h +54 -0
- include/mmg/libmmg.h +67 -0
- include/mmg/libmmgf.h +42 -0
- include/mmg/mmg2d/libmmg2d.h +2761 -0
- include/mmg/mmg2d/libmmg2df.h +3263 -0
- include/mmg/mmg2d/mmg2d_export.h +34 -0
- include/mmg/mmg3d/libmmg3d.h +3444 -0
- include/mmg/mmg3d/libmmg3df.h +4041 -0
- include/mmg/mmg3d/mmg3d_export.h +34 -0
- include/mmg/mmgs/libmmgs.h +2560 -0
- include/mmg/mmgs/libmmgsf.h +3028 -0
- include/mmg/mmgs/mmgs_export.h +34 -0
- lib/__init__.py +10 -0
- lib/cmake/mmg/FindElas.cmake +57 -0
- lib/cmake/mmg/FindSCOTCH.cmake +373 -0
- lib/cmake/mmg/MmgTargets-release.cmake +53 -0
- lib/cmake/mmg/MmgTargets.cmake +127 -0
- lib/cmake/mmg/mmgConfig.cmake +43 -0
- lib/mmg.lib +0 -0
- lib/mmg2d.lib +0 -0
- lib/mmg3d.lib +0 -0
- lib/mmgs.lib +0 -0
- mmgpy/__init__.py +888 -0
- mmgpy/_logging.py +86 -0
- mmgpy/_mmgpy.cp310-win_amd64.pyd +0 -0
- mmgpy/_mmgpy.pyi +650 -0
- mmgpy/_options.py +304 -0
- mmgpy/_progress.py +539 -0
- mmgpy/_pyvista.py +423 -0
- mmgpy/_version.py +3 -0
- mmgpy/_version.py.in +3 -0
- mmgpy/lagrangian.py +394 -0
- mmgpy/metrics.py +595 -0
- mmgpy/mmg2d.dll +0 -0
- mmgpy/mmg2d.lib +0 -0
- mmgpy/mmg3d.dll +0 -0
- mmgpy/mmg3d.lib +0 -0
- mmgpy/mmgs.dll +0 -0
- mmgpy/mmgs.lib +0 -0
- mmgpy/progress.py +57 -0
- mmgpy/py.typed +0 -0
- mmgpy/sizing.py +370 -0
- mmgpy-0.2.0.dist-info/DELVEWHEEL +2 -0
- mmgpy-0.2.0.dist-info/METADATA +75 -0
- mmgpy-0.2.0.dist-info/RECORD +129 -0
- mmgpy-0.2.0.dist-info/WHEEL +5 -0
- mmgpy-0.2.0.dist-info/entry_points.txt +6 -0
- mmgpy-0.2.0.dist-info/licenses/LICENSE +38 -0
- mmgpy.libs/vtkCommonColor-9.4-799ae0f43eb3a04510b0ed500c05e895.dll +0 -0
- mmgpy.libs/vtkCommonComputationalGeometry-9.4-e1ee47e9ca84c220e3fda21c864610e9.dll +0 -0
- mmgpy.libs/vtkCommonCore-9.4.dll +0 -0
- mmgpy.libs/vtkCommonDataModel-9.4.dll +0 -0
- mmgpy.libs/vtkCommonExecutionModel-9.4-5fea279cddbd0dd8e39907cbfb423d2c.dll +0 -0
- mmgpy.libs/vtkCommonMath-9.4-70aba6f1b0ad06008b5990b6843ff4e9.dll +0 -0
- mmgpy.libs/vtkCommonMisc-9.4-96697cc413673520510a54c05fa0ef99.dll +0 -0
- mmgpy.libs/vtkCommonSystem-9.4-a748ca3c31712678e4e0f2ff3b09785b.dll +0 -0
- mmgpy.libs/vtkCommonTransforms-9.4-11e72e99aca2003a38a3ff9bcfb90d92.dll +0 -0
- mmgpy.libs/vtkDICOMParser-9.4-6f27d14c12768aac52622cbd28ca0b3a.dll +0 -0
- mmgpy.libs/vtkFiltersCellGrid-9.4-5675f4c4a8440bd5f5981149f99315e8.dll +0 -0
- mmgpy.libs/vtkFiltersCore-9.4-ef29a82b399f8ffeec5dfa8c7e010901.dll +0 -0
- mmgpy.libs/vtkFiltersExtraction-9.4-6a452db7095d68b3af501d1b39a05670.dll +0 -0
- mmgpy.libs/vtkFiltersGeneral-9.4-b9b071ef41cba7c6468dd7e0a9f5d4bf.dll +0 -0
- mmgpy.libs/vtkFiltersGeometry-9.4-757f3c8b9a1fd9774cce83aec0c94c55.dll +0 -0
- mmgpy.libs/vtkFiltersHybrid-9.4-6b343077b9da30bb95fc4492762b9bed.dll +0 -0
- mmgpy.libs/vtkFiltersHyperTree-9.4-831d7e88dd11a3faec876929089d21e8.dll +0 -0
- mmgpy.libs/vtkFiltersModeling-9.4-a3fc680a4836e8913376390217ceae1e.dll +0 -0
- mmgpy.libs/vtkFiltersParallel-9.4-5307d8b619459bb2aeb13c2872cebc2b.dll +0 -0
- mmgpy.libs/vtkFiltersReduction-9.4-f7abe86bfcde726b6e7daec4773a089f.dll +0 -0
- mmgpy.libs/vtkFiltersSources-9.4-d38546a5e2bfd83ea0a70f5be4fa7fdc.dll +0 -0
- mmgpy.libs/vtkFiltersStatistics-9.4-d2abec2372ab98574cdbd0461c73d459.dll +0 -0
- mmgpy.libs/vtkFiltersTexture-9.4-a374b3cfe75e10483976a6a6780ca1ca.dll +0 -0
- mmgpy.libs/vtkFiltersVerdict-9.4-a6a276b6e0d3ac6d042f192842c9382a.dll +0 -0
- mmgpy.libs/vtkIOCellGrid-9.4-0df3bee5d56b2062dad430b53f81f06a.dll +0 -0
- mmgpy.libs/vtkIOCore-9.4.dll +0 -0
- mmgpy.libs/vtkIOGeometry-9.4-13e2301d83eea31e8df955a8dd196eb1.dll +0 -0
- mmgpy.libs/vtkIOImage-9.4-666beab0c43da6c4b2c59fba464bb6b1.dll +0 -0
- mmgpy.libs/vtkIOLegacy-9.4.dll +0 -0
- mmgpy.libs/vtkIOParallel-9.4.dll +0 -0
- mmgpy.libs/vtkIOParallelXML-9.4.dll +0 -0
- mmgpy.libs/vtkIOXML-9.4.dll +0 -0
- mmgpy.libs/vtkIOXMLParser-9.4-f4144aed6a73ee50eefeae75a78fd71b.dll +0 -0
- mmgpy.libs/vtkImagingCore-9.4-ecc92d2d09d8ac4e8f3b199a917f96fd.dll +0 -0
- mmgpy.libs/vtkImagingSources-9.4-944fcaf71940d51ed5dc1b5c8eba2571.dll +0 -0
- mmgpy.libs/vtkParallelCore-9.4-114ce4e5a12302a9f3c3485ab88d5a39.dll +0 -0
- mmgpy.libs/vtkParallelDIY-9.4-7add130df7f5139505a17ee72afefa41.dll +0 -0
- mmgpy.libs/vtkRenderingCore-9.4-ec5612bc182f43047add4c6a55050be4.dll +0 -0
- mmgpy.libs/vtkdoubleconversion-9.4-676429e05704a1fd81323494aba16669.dll +0 -0
- mmgpy.libs/vtkexpat-9.4-58e3b6d3064cf0e02659e3a57f60f779.dll +0 -0
- mmgpy.libs/vtkfmt-9.4-fd2ae0aaa19f2f735b93d4feb613d558.dll +0 -0
- mmgpy.libs/vtkjpeg-9.4-2fd58669e746a0d571706ff3f4c1896f.dll +0 -0
- mmgpy.libs/vtkjsoncpp-9.4-c2076501decec6ce45be5280d480c02d.dll +0 -0
- mmgpy.libs/vtkkissfft-9.4-874ed77ec96808d2e395a6caeb69abbe.dll +0 -0
- mmgpy.libs/vtkloguru-9.4-1038f41dd2d3acc7d894c1d57b428cc6.dll +0 -0
- mmgpy.libs/vtklz4-9.4-9982d6f8f47ac19965668cd3c2926473.dll +0 -0
- mmgpy.libs/vtklzma-9.4-a473d065be12f766957c699a0aefac38.dll +0 -0
- mmgpy.libs/vtkmetaio-9.4-aa48920e94a28f23d08054f5e82867f4.dll +0 -0
- mmgpy.libs/vtkpng-9.4-cbefdfbef5c0d4dd7ae43b9d526e881a.dll +0 -0
- mmgpy.libs/vtkpugixml-9.4-9c7652d9a42fd99e62753e7d3fd87ee9.dll +0 -0
- mmgpy.libs/vtksys-9.4.dll +0 -0
- mmgpy.libs/vtktiff-9.4-9822dcf52447c045cf9a70960d45a9bd.dll +0 -0
- mmgpy.libs/vtktoken-9.4-471c14923651cbbd86067852f347807b.dll +0 -0
- mmgpy.libs/vtkverdict-9.4-c549882a3b8671666be1366008f27f7e.dll +0 -0
- mmgpy.libs/vtkzlib-9.4-3b9ffa51c80ccd91bb22a4c3ca11a8d7.dll +0 -0
- share/__init__.py +10 -0
- share/man/man1/mmg2d.1.gz +0 -0
- share/man/man1/mmg3d.1.gz +0 -0
- share/man/man1/mmgs.1.gz +0 -0
mmgpy/_pyvista.py
ADDED
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
"""PyVista integration for mmgpy mesh classes.
|
|
2
|
+
|
|
3
|
+
This module provides conversion functions between PyVista mesh types
|
|
4
|
+
and mmgpy mesh classes.
|
|
5
|
+
|
|
6
|
+
Example:
|
|
7
|
+
>>> import pyvista as pv
|
|
8
|
+
>>> from mmgpy import MmgMesh3D, from_pyvista, to_pyvista
|
|
9
|
+
>>>
|
|
10
|
+
>>> # Load mesh and convert to mmgpy
|
|
11
|
+
>>> grid = pv.read("mesh.vtk")
|
|
12
|
+
>>> mesh = from_pyvista(grid)
|
|
13
|
+
>>>
|
|
14
|
+
>>> # Remesh and convert back
|
|
15
|
+
>>> mesh.remesh(hmax=0.1)
|
|
16
|
+
>>> result = to_pyvista(mesh)
|
|
17
|
+
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
from typing import TYPE_CHECKING, overload
|
|
23
|
+
|
|
24
|
+
import numpy as np
|
|
25
|
+
import pyvista as pv
|
|
26
|
+
|
|
27
|
+
from mmgpy._mmgpy import MmgMesh2D, MmgMesh3D, MmgMeshS
|
|
28
|
+
|
|
29
|
+
if TYPE_CHECKING:
|
|
30
|
+
from numpy.typing import NDArray
|
|
31
|
+
|
|
32
|
+
_DIMS_2D = 2
|
|
33
|
+
_DIMS_3D = 3
|
|
34
|
+
_TRIANGLE_VERTS = 3
|
|
35
|
+
_2D_DETECTION_TOLERANCE = 1e-8
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _is_2d_mesh(points: NDArray[np.floating]) -> bool:
|
|
39
|
+
"""Check if points are essentially 2D (z coordinates are zero or near-zero)."""
|
|
40
|
+
if points.shape[1] == _DIMS_2D:
|
|
41
|
+
return True
|
|
42
|
+
if points.shape[1] == _DIMS_3D:
|
|
43
|
+
z_coords = points[:, 2]
|
|
44
|
+
return bool(np.allclose(z_coords, 0, atol=_2D_DETECTION_TOLERANCE))
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _extract_triangles_from_polydata(mesh: pv.PolyData) -> NDArray[np.int32]:
|
|
49
|
+
"""Extract triangle connectivity from PolyData faces array."""
|
|
50
|
+
if hasattr(mesh, "cells_dict") and pv.CellType.TRIANGLE in mesh.cells_dict:
|
|
51
|
+
return mesh.cells_dict[pv.CellType.TRIANGLE].astype(np.int32)
|
|
52
|
+
|
|
53
|
+
faces = mesh.faces
|
|
54
|
+
if len(faces) == 0:
|
|
55
|
+
msg = "PolyData has no faces"
|
|
56
|
+
raise ValueError(msg)
|
|
57
|
+
|
|
58
|
+
triangles = []
|
|
59
|
+
i = 0
|
|
60
|
+
while i < len(faces):
|
|
61
|
+
n_verts = faces[i]
|
|
62
|
+
if n_verts != _TRIANGLE_VERTS:
|
|
63
|
+
msg = f"Expected triangles (3 vertices), got {n_verts}-vertex polygon"
|
|
64
|
+
raise ValueError(msg)
|
|
65
|
+
triangles.append(faces[i + 1 : i + 4])
|
|
66
|
+
i += n_verts + 1
|
|
67
|
+
|
|
68
|
+
return np.array(triangles, dtype=np.int32)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _from_pyvista_to_mmg3d(mesh: pv.UnstructuredGrid) -> MmgMesh3D:
|
|
72
|
+
"""Convert UnstructuredGrid with tetrahedra to MmgMesh3D."""
|
|
73
|
+
if pv.CellType.TETRA not in mesh.cells_dict:
|
|
74
|
+
msg = "UnstructuredGrid must contain tetrahedra (CellType.TETRA)"
|
|
75
|
+
raise ValueError(msg)
|
|
76
|
+
|
|
77
|
+
vertices = np.array(mesh.points, dtype=np.float64)
|
|
78
|
+
elements = mesh.cells_dict[pv.CellType.TETRA].astype(np.int32)
|
|
79
|
+
|
|
80
|
+
return MmgMesh3D(vertices, elements)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _from_pyvista_to_mmg2d(mesh: pv.PolyData) -> MmgMesh2D:
|
|
84
|
+
"""Convert PolyData with 2D triangles to MmgMesh2D."""
|
|
85
|
+
points = np.array(mesh.points, dtype=np.float64)
|
|
86
|
+
if points.shape[1] == _DIMS_3D:
|
|
87
|
+
vertices = np.ascontiguousarray(points[:, :2])
|
|
88
|
+
else:
|
|
89
|
+
vertices = points
|
|
90
|
+
triangles = _extract_triangles_from_polydata(mesh)
|
|
91
|
+
|
|
92
|
+
return MmgMesh2D(vertices, triangles)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _from_pyvista_to_mmgs(mesh: pv.PolyData) -> MmgMeshS:
|
|
96
|
+
"""Convert PolyData with 3D surface triangles to MmgMeshS."""
|
|
97
|
+
vertices = np.array(mesh.points, dtype=np.float64)
|
|
98
|
+
triangles = _extract_triangles_from_polydata(mesh)
|
|
99
|
+
|
|
100
|
+
return MmgMeshS(vertices, triangles)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _from_pyvista_with_explicit_type(
|
|
104
|
+
mesh: pv.UnstructuredGrid | pv.PolyData,
|
|
105
|
+
mesh_type: type[MmgMesh3D | MmgMesh2D | MmgMeshS],
|
|
106
|
+
) -> MmgMesh3D | MmgMesh2D | MmgMeshS:
|
|
107
|
+
"""Convert PyVista mesh to mmgpy mesh with explicit type."""
|
|
108
|
+
if mesh_type is MmgMesh3D:
|
|
109
|
+
if not isinstance(mesh, pv.UnstructuredGrid):
|
|
110
|
+
msg = "MmgMesh3D requires UnstructuredGrid input"
|
|
111
|
+
raise ValueError(msg)
|
|
112
|
+
return _from_pyvista_to_mmg3d(mesh)
|
|
113
|
+
|
|
114
|
+
if mesh_type is MmgMesh2D:
|
|
115
|
+
if not isinstance(mesh, pv.PolyData):
|
|
116
|
+
msg = "MmgMesh2D requires PolyData input"
|
|
117
|
+
raise ValueError(msg)
|
|
118
|
+
return _from_pyvista_to_mmg2d(mesh)
|
|
119
|
+
|
|
120
|
+
if mesh_type is MmgMeshS:
|
|
121
|
+
if not isinstance(mesh, pv.PolyData):
|
|
122
|
+
msg = "MmgMeshS requires PolyData input"
|
|
123
|
+
raise ValueError(msg)
|
|
124
|
+
return _from_pyvista_to_mmgs(mesh)
|
|
125
|
+
|
|
126
|
+
msg = f"Unknown mesh type: {mesh_type}"
|
|
127
|
+
raise ValueError(msg)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _from_pyvista_auto_detect(
|
|
131
|
+
mesh: pv.UnstructuredGrid | pv.PolyData,
|
|
132
|
+
) -> MmgMesh3D | MmgMesh2D | MmgMeshS:
|
|
133
|
+
"""Convert PyVista mesh to mmgpy mesh with auto-detection."""
|
|
134
|
+
if isinstance(mesh, pv.UnstructuredGrid):
|
|
135
|
+
if pv.CellType.TETRA in mesh.cells_dict:
|
|
136
|
+
return _from_pyvista_to_mmg3d(mesh)
|
|
137
|
+
msg = "UnstructuredGrid must contain tetrahedra for auto-detection"
|
|
138
|
+
raise ValueError(msg)
|
|
139
|
+
|
|
140
|
+
if isinstance(mesh, pv.PolyData):
|
|
141
|
+
if _is_2d_mesh(mesh.points):
|
|
142
|
+
return _from_pyvista_to_mmg2d(mesh)
|
|
143
|
+
return _from_pyvista_to_mmgs(mesh)
|
|
144
|
+
|
|
145
|
+
msg = f"Unsupported PyVista mesh type: {type(mesh)}"
|
|
146
|
+
raise TypeError(msg)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
@overload
|
|
150
|
+
def from_pyvista(
|
|
151
|
+
mesh: pv.UnstructuredGrid | pv.PolyData,
|
|
152
|
+
mesh_type: type[MmgMesh3D],
|
|
153
|
+
) -> MmgMesh3D: ...
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@overload
|
|
157
|
+
def from_pyvista(
|
|
158
|
+
mesh: pv.UnstructuredGrid | pv.PolyData,
|
|
159
|
+
mesh_type: type[MmgMesh2D],
|
|
160
|
+
) -> MmgMesh2D: ...
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
@overload
|
|
164
|
+
def from_pyvista(
|
|
165
|
+
mesh: pv.UnstructuredGrid | pv.PolyData,
|
|
166
|
+
mesh_type: type[MmgMeshS],
|
|
167
|
+
) -> MmgMeshS: ...
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@overload
|
|
171
|
+
def from_pyvista(
|
|
172
|
+
mesh: pv.UnstructuredGrid | pv.PolyData,
|
|
173
|
+
mesh_type: None = None,
|
|
174
|
+
) -> MmgMesh3D | MmgMesh2D | MmgMeshS: ...
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def from_pyvista(
|
|
178
|
+
mesh: pv.UnstructuredGrid | pv.PolyData,
|
|
179
|
+
mesh_type: type[MmgMesh3D | MmgMesh2D | MmgMeshS] | None = None,
|
|
180
|
+
) -> MmgMesh3D | MmgMesh2D | MmgMeshS:
|
|
181
|
+
"""Convert a PyVista mesh to an mmgpy mesh.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
mesh: PyVista mesh (UnstructuredGrid or PolyData).
|
|
185
|
+
mesh_type: Target mesh class. If None, auto-detects based on:
|
|
186
|
+
- UnstructuredGrid with tetrahedra → MmgMesh3D
|
|
187
|
+
- PolyData with 2D points (z≈0) → MmgMesh2D
|
|
188
|
+
- PolyData with 3D points → MmgMeshS
|
|
189
|
+
|
|
190
|
+
Returns:
|
|
191
|
+
The appropriate mmgpy mesh instance.
|
|
192
|
+
|
|
193
|
+
Raises:
|
|
194
|
+
ValueError: If mesh type cannot be determined or is incompatible.
|
|
195
|
+
|
|
196
|
+
Note:
|
|
197
|
+
When auto-detecting mesh type for PolyData, a mesh is considered 2D
|
|
198
|
+
(and converted to MmgMesh2D) if all z-coordinates are within 1e-8 of zero.
|
|
199
|
+
For thin 3D meshes near z=0, explicitly specify ``mesh_type=MmgMeshS``.
|
|
200
|
+
|
|
201
|
+
Example:
|
|
202
|
+
>>> import pyvista as pv
|
|
203
|
+
>>> from mmgpy import from_pyvista, MmgMeshS
|
|
204
|
+
>>>
|
|
205
|
+
>>> # Auto-detect mesh type
|
|
206
|
+
>>> grid = pv.read("tetra_mesh.vtk")
|
|
207
|
+
>>> mesh3d = from_pyvista(grid)
|
|
208
|
+
>>>
|
|
209
|
+
>>> # Explicit mesh type for thin 3D surfaces
|
|
210
|
+
>>> surface = pv.read("surface.stl")
|
|
211
|
+
>>> mesh_s = from_pyvista(surface, MmgMeshS)
|
|
212
|
+
|
|
213
|
+
"""
|
|
214
|
+
if mesh_type is not None:
|
|
215
|
+
return _from_pyvista_with_explicit_type(mesh, mesh_type)
|
|
216
|
+
return _from_pyvista_auto_detect(mesh)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
@overload
|
|
220
|
+
def to_pyvista(
|
|
221
|
+
mesh: MmgMesh3D,
|
|
222
|
+
*,
|
|
223
|
+
include_refs: bool = True,
|
|
224
|
+
) -> pv.UnstructuredGrid: ...
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
@overload
|
|
228
|
+
def to_pyvista(
|
|
229
|
+
mesh: MmgMesh2D,
|
|
230
|
+
*,
|
|
231
|
+
include_refs: bool = True,
|
|
232
|
+
) -> pv.PolyData: ...
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
@overload
|
|
236
|
+
def to_pyvista(
|
|
237
|
+
mesh: MmgMeshS,
|
|
238
|
+
*,
|
|
239
|
+
include_refs: bool = True,
|
|
240
|
+
) -> pv.PolyData: ...
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def to_pyvista(
|
|
244
|
+
mesh: MmgMesh3D | MmgMesh2D | MmgMeshS,
|
|
245
|
+
*,
|
|
246
|
+
include_refs: bool = True,
|
|
247
|
+
) -> pv.UnstructuredGrid | pv.PolyData:
|
|
248
|
+
"""Convert an mmgpy mesh to a PyVista mesh.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
mesh: mmgpy mesh instance (MmgMesh3D, MmgMesh2D, or MmgMeshS).
|
|
252
|
+
include_refs: If True, include element references as cell_data.
|
|
253
|
+
|
|
254
|
+
Returns:
|
|
255
|
+
PyVista mesh:
|
|
256
|
+
- MmgMesh3D → UnstructuredGrid with tetrahedra
|
|
257
|
+
- MmgMesh2D → PolyData with triangular faces (z=0)
|
|
258
|
+
- MmgMeshS → PolyData with triangular faces
|
|
259
|
+
|
|
260
|
+
Raises:
|
|
261
|
+
TypeError: If mesh is not an mmgpy mesh type.
|
|
262
|
+
|
|
263
|
+
Example:
|
|
264
|
+
>>> from mmgpy import MmgMesh3D, to_pyvista
|
|
265
|
+
>>>
|
|
266
|
+
>>> mesh = MmgMesh3D(vertices, elements)
|
|
267
|
+
>>> mesh.remesh(hmax=0.1)
|
|
268
|
+
>>> grid = to_pyvista(mesh)
|
|
269
|
+
>>> grid.plot()
|
|
270
|
+
|
|
271
|
+
"""
|
|
272
|
+
if isinstance(mesh, MmgMesh3D):
|
|
273
|
+
return _mmg3d_to_pyvista(mesh, include_refs=include_refs)
|
|
274
|
+
if isinstance(mesh, MmgMesh2D):
|
|
275
|
+
return _mmg2d_to_pyvista(mesh, include_refs=include_refs)
|
|
276
|
+
if isinstance(mesh, MmgMeshS):
|
|
277
|
+
return _mmgs_to_pyvista(mesh, include_refs=include_refs)
|
|
278
|
+
|
|
279
|
+
msg = f"Unsupported mesh type: {type(mesh)}"
|
|
280
|
+
raise TypeError(msg)
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def _mmg3d_to_pyvista(mesh: MmgMesh3D, *, include_refs: bool) -> pv.UnstructuredGrid:
|
|
284
|
+
"""Convert MmgMesh3D to PyVista UnstructuredGrid."""
|
|
285
|
+
vertices = mesh.get_vertices()
|
|
286
|
+
|
|
287
|
+
if include_refs:
|
|
288
|
+
elements, refs = mesh.get_elements_with_refs()
|
|
289
|
+
else:
|
|
290
|
+
elements = mesh.get_elements()
|
|
291
|
+
refs = None
|
|
292
|
+
|
|
293
|
+
grid = pv.UnstructuredGrid({pv.CellType.TETRA: elements}, vertices)
|
|
294
|
+
|
|
295
|
+
if refs is not None:
|
|
296
|
+
grid.cell_data["refs"] = refs
|
|
297
|
+
|
|
298
|
+
return grid
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def _mmg2d_to_pyvista(mesh: MmgMesh2D, *, include_refs: bool) -> pv.PolyData:
|
|
302
|
+
"""Convert MmgMesh2D to PyVista PolyData."""
|
|
303
|
+
vertices_2d = mesh.get_vertices()
|
|
304
|
+
vertices_3d = np.column_stack([vertices_2d, np.zeros(len(vertices_2d))])
|
|
305
|
+
|
|
306
|
+
if include_refs:
|
|
307
|
+
triangles, refs = mesh.get_triangles_with_refs()
|
|
308
|
+
else:
|
|
309
|
+
triangles = mesh.get_triangles()
|
|
310
|
+
refs = None
|
|
311
|
+
|
|
312
|
+
faces = np.hstack(
|
|
313
|
+
[np.full((len(triangles), 1), _TRIANGLE_VERTS), triangles],
|
|
314
|
+
).ravel()
|
|
315
|
+
polydata = pv.PolyData(vertices_3d, faces=faces)
|
|
316
|
+
|
|
317
|
+
if refs is not None:
|
|
318
|
+
polydata.cell_data["refs"] = refs
|
|
319
|
+
|
|
320
|
+
return polydata
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def _mmgs_to_pyvista(mesh: MmgMeshS, *, include_refs: bool) -> pv.PolyData:
|
|
324
|
+
"""Convert MmgMeshS to PyVista PolyData."""
|
|
325
|
+
vertices = mesh.get_vertices()
|
|
326
|
+
|
|
327
|
+
if include_refs:
|
|
328
|
+
triangles, refs = mesh.get_triangles_with_refs()
|
|
329
|
+
else:
|
|
330
|
+
triangles = mesh.get_triangles()
|
|
331
|
+
refs = None
|
|
332
|
+
|
|
333
|
+
faces = np.hstack(
|
|
334
|
+
[np.full((len(triangles), 1), _TRIANGLE_VERTS), triangles],
|
|
335
|
+
).ravel()
|
|
336
|
+
polydata = pv.PolyData(vertices, faces=faces)
|
|
337
|
+
|
|
338
|
+
if refs is not None:
|
|
339
|
+
polydata.cell_data["refs"] = refs
|
|
340
|
+
|
|
341
|
+
return polydata
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def _mmg3d_from_pyvista(
|
|
345
|
+
cls: type[MmgMesh3D], # noqa: ARG001
|
|
346
|
+
mesh: pv.UnstructuredGrid | pv.PolyData,
|
|
347
|
+
) -> MmgMesh3D:
|
|
348
|
+
"""Create MmgMesh3D from a PyVista mesh."""
|
|
349
|
+
if not isinstance(mesh, pv.UnstructuredGrid):
|
|
350
|
+
msg = "MmgMesh3D.from_pyvista requires UnstructuredGrid input"
|
|
351
|
+
raise TypeError(msg)
|
|
352
|
+
return _from_pyvista_to_mmg3d(mesh)
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def _mmg2d_from_pyvista(
|
|
356
|
+
cls: type[MmgMesh2D], # noqa: ARG001
|
|
357
|
+
mesh: pv.UnstructuredGrid | pv.PolyData,
|
|
358
|
+
) -> MmgMesh2D:
|
|
359
|
+
"""Create MmgMesh2D from a PyVista mesh."""
|
|
360
|
+
if not isinstance(mesh, pv.PolyData):
|
|
361
|
+
msg = "MmgMesh2D.from_pyvista requires PolyData input"
|
|
362
|
+
raise TypeError(msg)
|
|
363
|
+
return _from_pyvista_to_mmg2d(mesh)
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
def _mmgs_from_pyvista(
|
|
367
|
+
cls: type[MmgMeshS], # noqa: ARG001
|
|
368
|
+
mesh: pv.UnstructuredGrid | pv.PolyData,
|
|
369
|
+
) -> MmgMeshS:
|
|
370
|
+
"""Create MmgMeshS from a PyVista mesh."""
|
|
371
|
+
if not isinstance(mesh, pv.PolyData):
|
|
372
|
+
msg = "MmgMeshS.from_pyvista requires PolyData input"
|
|
373
|
+
raise TypeError(msg)
|
|
374
|
+
return _from_pyvista_to_mmgs(mesh)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def _mmg3d_to_pyvista_method(
|
|
378
|
+
self: MmgMesh3D,
|
|
379
|
+
*,
|
|
380
|
+
include_refs: bool = True,
|
|
381
|
+
) -> pv.UnstructuredGrid:
|
|
382
|
+
"""Convert MmgMesh3D to a PyVista UnstructuredGrid."""
|
|
383
|
+
return _mmg3d_to_pyvista(self, include_refs=include_refs)
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
def _mmg2d_to_pyvista_method(
|
|
387
|
+
self: MmgMesh2D,
|
|
388
|
+
*,
|
|
389
|
+
include_refs: bool = True,
|
|
390
|
+
) -> pv.PolyData:
|
|
391
|
+
"""Convert MmgMesh2D to a PyVista PolyData."""
|
|
392
|
+
return _mmg2d_to_pyvista(self, include_refs=include_refs)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def _mmgs_to_pyvista_method(
|
|
396
|
+
self: MmgMeshS,
|
|
397
|
+
*,
|
|
398
|
+
include_refs: bool = True,
|
|
399
|
+
) -> pv.PolyData:
|
|
400
|
+
"""Convert MmgMeshS to a PyVista PolyData."""
|
|
401
|
+
return _mmgs_to_pyvista(self, include_refs=include_refs)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
def add_pyvista_methods() -> None:
|
|
405
|
+
"""Add PyVista methods to mesh classes.
|
|
406
|
+
|
|
407
|
+
Call this function to add `from_pyvista` classmethod and `to_pyvista`
|
|
408
|
+
instance method to MmgMesh3D, MmgMesh2D, and MmgMeshS classes.
|
|
409
|
+
|
|
410
|
+
These methods are automatically called at import time.
|
|
411
|
+
"""
|
|
412
|
+
# Add classmethods - type ignores needed for monkey-patching pybind11 classes
|
|
413
|
+
MmgMesh3D.from_pyvista = classmethod(_mmg3d_from_pyvista) # type: ignore[attr-defined]
|
|
414
|
+
MmgMesh2D.from_pyvista = classmethod(_mmg2d_from_pyvista) # type: ignore[attr-defined]
|
|
415
|
+
MmgMeshS.from_pyvista = classmethod(_mmgs_from_pyvista) # type: ignore[attr-defined]
|
|
416
|
+
|
|
417
|
+
# Add instance methods
|
|
418
|
+
MmgMesh3D.to_pyvista = _mmg3d_to_pyvista_method # type: ignore[attr-defined]
|
|
419
|
+
MmgMesh2D.to_pyvista = _mmg2d_to_pyvista_method # type: ignore[attr-defined]
|
|
420
|
+
MmgMeshS.to_pyvista = _mmgs_to_pyvista_method # type: ignore[attr-defined]
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
__all__ = ["add_pyvista_methods", "from_pyvista", "to_pyvista"]
|
mmgpy/_version.py
ADDED
mmgpy/_version.py.in
ADDED