mmgpy 0.3.0__cp312-cp312-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/Release/mmg2d_O3.exe +0 -0
- bin/Release/mmg3d_O3.exe +0 -0
- bin/Release/mmgs_O3.exe +0 -0
- 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.cp312-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.3.0.dist-info/DELVEWHEEL +2 -0
- mmgpy-0.3.0.dist-info/METADATA +75 -0
- mmgpy-0.3.0.dist-info/RECORD +132 -0
- mmgpy-0.3.0.dist-info/WHEEL +5 -0
- mmgpy-0.3.0.dist-info/entry_points.txt +6 -0
- mmgpy-0.3.0.dist-info/licenses/LICENSE +38 -0
- mmgpy.libs/vtkCommonColor-9.5-07cd19e9d77559cb8be83e8ac8833cd4.dll +0 -0
- mmgpy.libs/vtkCommonComputationalGeometry-9.5-4aaf997b087c330e171c14a4ba6be7b2.dll +0 -0
- mmgpy.libs/vtkCommonCore-9.5.dll +0 -0
- mmgpy.libs/vtkCommonDataModel-9.5.dll +0 -0
- mmgpy.libs/vtkCommonExecutionModel-9.5-2f7a1bae0a1d4d0e205eea43596a659c.dll +0 -0
- mmgpy.libs/vtkCommonMath-9.5-609b01246386fe29df2677fa5c7ca793.dll +0 -0
- mmgpy.libs/vtkCommonMisc-9.5-4173df33811eddea1529a40bf93266c8.dll +0 -0
- mmgpy.libs/vtkCommonSystem-9.5-e5b15bd84934b99e3b2bbe5d3e064c97.dll +0 -0
- mmgpy.libs/vtkCommonTransforms-9.5-9b76a61640718d893271cc0b5db50d1d.dll +0 -0
- mmgpy.libs/vtkDICOMParser-9.5-203c95a77d21799a8049a576e1b28f2e.dll +0 -0
- mmgpy.libs/vtkFiltersCellGrid-9.5-fa6bda61d2d528369d8b2f3a66d2d6b4.dll +0 -0
- mmgpy.libs/vtkFiltersCore-9.5-935a5f5225a975e99626296b2f3ded70.dll +0 -0
- mmgpy.libs/vtkFiltersExtraction-9.5-dc0a7543ba584f7e8ce9f9184485a228.dll +0 -0
- mmgpy.libs/vtkFiltersGeneral-9.5-709f69dbcca8aba1750582106a97c605.dll +0 -0
- mmgpy.libs/vtkFiltersGeometry-9.5-7abfb655763a62f56d63b45038d6e811.dll +0 -0
- mmgpy.libs/vtkFiltersHybrid-9.5-0721ec98d8a8b7442d900747e1ec59fb.dll +0 -0
- mmgpy.libs/vtkFiltersHyperTree-9.5-f9ee6a4761fdad8956c08a51dae77636.dll +0 -0
- mmgpy.libs/vtkFiltersModeling-9.5-458d9d2c544bb3c37de28c26c05c07bc.dll +0 -0
- mmgpy.libs/vtkFiltersParallel-9.5-1f243ffe308277c3970d8be4172d856f.dll +0 -0
- mmgpy.libs/vtkFiltersReduction-9.5-bf8c4a248bd84fbd6bb1a2ab5f646e56.dll +0 -0
- mmgpy.libs/vtkFiltersSources-9.5-492fa5b1b8562f4b141a347a38ae1ce5.dll +0 -0
- mmgpy.libs/vtkFiltersStatistics-9.5-6e99ef76387303ec5ff8c0fe6101d446.dll +0 -0
- mmgpy.libs/vtkFiltersTexture-9.5-15c23120b41b9a1c4acb01f790aad01f.dll +0 -0
- mmgpy.libs/vtkFiltersVerdict-9.5-332c0402a58129ec5b6af7b7f56cbb62.dll +0 -0
- mmgpy.libs/vtkIOCellGrid-9.5-88e1ec9c5a3554a82aedc0027fe84c6b.dll +0 -0
- mmgpy.libs/vtkIOCore-9.5.dll +0 -0
- mmgpy.libs/vtkIOGeometry-9.5-47c69db15c63c5773efa6851b59ae0a7.dll +0 -0
- mmgpy.libs/vtkIOImage-9.5-74bb92e688da5595ff9ff7645f9a0a13.dll +0 -0
- mmgpy.libs/vtkIOLegacy-9.5.dll +0 -0
- mmgpy.libs/vtkIOParallel-9.5.dll +0 -0
- mmgpy.libs/vtkIOParallelXML-9.5.dll +0 -0
- mmgpy.libs/vtkIOXML-9.5.dll +0 -0
- mmgpy.libs/vtkIOXMLParser-9.5-1893156c41fd4cf7165904675cb5d15d.dll +0 -0
- mmgpy.libs/vtkImagingCore-9.5-145fc0249cffbd27c610d10812e1cbfc.dll +0 -0
- mmgpy.libs/vtkImagingSources-9.5-f0c087a4669caa045584ed61f52502b7.dll +0 -0
- mmgpy.libs/vtkParallelCore-9.5-e91757b6dbd2a5369ab2bd05ff95d79d.dll +0 -0
- mmgpy.libs/vtkParallelDIY-9.5-04dd6b6b5dd8a5eacd43d270999cf09a.dll +0 -0
- mmgpy.libs/vtkRenderingCore-9.5-24a9802d77a083def26449fa681b1af7.dll +0 -0
- mmgpy.libs/vtkdoubleconversion-9.5-5e39712b9f4e44ea8a26e9119e53a7d4.dll +0 -0
- mmgpy.libs/vtkexpat-9.5-3b1dd25e09a2cccbbac723de448cb894.dll +0 -0
- mmgpy.libs/vtkfmt-9.5-50239b66bf315d100ecd306114139e9b.dll +0 -0
- mmgpy.libs/vtkjpeg-9.5-9412ee79f685a9196398b988a59666cd.dll +0 -0
- mmgpy.libs/vtkjsoncpp-9.5-abfad956527e3a4885dbb39f99f9e4d4.dll +0 -0
- mmgpy.libs/vtkkissfft-9.5-464db9175ce63de19addc69be524c4b7.dll +0 -0
- mmgpy.libs/vtkloguru-9.5-ec016ed005b4a79062e329ad8f1c382d.dll +0 -0
- mmgpy.libs/vtklz4-9.5-798b58f4518733b0eee8027eeba022fb.dll +0 -0
- mmgpy.libs/vtklzma-9.5-8f489b5430eb47d578de52c769a4dd5c.dll +0 -0
- mmgpy.libs/vtkmetaio-9.5-8f0a559399d53e4c7fc06272620b2167.dll +0 -0
- mmgpy.libs/vtkpng-9.5-1dbed3116ba7e31f56512a93b942cdf5.dll +0 -0
- mmgpy.libs/vtkpugixml-9.5-23ef37d65494ab52babc6d45b24764b7.dll +0 -0
- mmgpy.libs/vtksys-9.5.dll +0 -0
- mmgpy.libs/vtktiff-9.5-767fd93c8402517d5b2d1befab98c41e.dll +0 -0
- mmgpy.libs/vtktoken-9.5-f4ff567202eeb9a613c0b242aa05dbc9.dll +0 -0
- mmgpy.libs/vtkverdict-9.5-6bb84649d1b0ca1cc5454307fd35083b.dll +0 -0
- mmgpy.libs/vtkzlib-9.5-779937c44671e188e9f96125eb5afb12.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/_progress.py
ADDED
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
"""Progress callback utilities for mmgpy with Rich integration."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
from contextlib import contextmanager
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import TYPE_CHECKING, Protocol
|
|
9
|
+
|
|
10
|
+
if sys.version_info >= (3, 11):
|
|
11
|
+
from typing import Self
|
|
12
|
+
else:
|
|
13
|
+
from typing_extensions import Self
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from collections.abc import Callable, Generator
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
import numpy as np
|
|
21
|
+
from numpy.typing import NDArray
|
|
22
|
+
|
|
23
|
+
from ._mmgpy import MmgMesh2D, MmgMesh3D, MmgMeshS
|
|
24
|
+
|
|
25
|
+
MeshType = MmgMesh3D | MmgMesh2D | MmgMeshS
|
|
26
|
+
ProgressCallback = Callable[["ProgressEvent"], None]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass
|
|
30
|
+
class ProgressEvent:
|
|
31
|
+
"""Event emitted during mesh operations.
|
|
32
|
+
|
|
33
|
+
Attributes
|
|
34
|
+
----------
|
|
35
|
+
phase : str
|
|
36
|
+
The current phase of the operation. One of:
|
|
37
|
+
- "init": Initializing mesh structures
|
|
38
|
+
- "load": Loading mesh from file
|
|
39
|
+
- "options": Setting remeshing options
|
|
40
|
+
- "remesh": Performing remeshing (status="start" or "complete")
|
|
41
|
+
- "save": Saving mesh to file
|
|
42
|
+
status : str
|
|
43
|
+
Status within the phase ("start", "complete", or "progress").
|
|
44
|
+
message : str
|
|
45
|
+
Human-readable description of what's happening.
|
|
46
|
+
details : dict[str, Any] | None
|
|
47
|
+
Optional additional details (e.g., vertex/element counts after remesh).
|
|
48
|
+
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
phase: str
|
|
52
|
+
status: str
|
|
53
|
+
message: str
|
|
54
|
+
details: dict[str, Any] | None = None
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class ProgressReporter(Protocol):
|
|
58
|
+
"""Protocol for progress reporters."""
|
|
59
|
+
|
|
60
|
+
def __call__(self, event: ProgressEvent) -> None:
|
|
61
|
+
"""Report a progress event."""
|
|
62
|
+
...
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _emit_event(
|
|
66
|
+
callback: ProgressCallback | None,
|
|
67
|
+
phase: str,
|
|
68
|
+
status: str,
|
|
69
|
+
message: str,
|
|
70
|
+
details: dict[str, Any] | None = None,
|
|
71
|
+
) -> None:
|
|
72
|
+
"""Emit a progress event if callback is provided."""
|
|
73
|
+
if callback is not None:
|
|
74
|
+
event = ProgressEvent(
|
|
75
|
+
phase=phase,
|
|
76
|
+
status=status,
|
|
77
|
+
message=message,
|
|
78
|
+
details=details,
|
|
79
|
+
)
|
|
80
|
+
callback(event)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class LoggingProgressReporter:
|
|
84
|
+
"""Progress reporter that logs events using mmgpy's logger."""
|
|
85
|
+
|
|
86
|
+
def __init__(self) -> None:
|
|
87
|
+
from ._logging import get_logger
|
|
88
|
+
|
|
89
|
+
self._logger = get_logger()
|
|
90
|
+
|
|
91
|
+
def __call__(self, event: ProgressEvent) -> None:
|
|
92
|
+
"""Log the progress event."""
|
|
93
|
+
msg = f"[{event.phase}] {event.message}"
|
|
94
|
+
if event.details:
|
|
95
|
+
details_str = ", ".join(f"{k}={v}" for k, v in event.details.items())
|
|
96
|
+
msg = f"{msg} ({details_str})"
|
|
97
|
+
self._logger.info(msg)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class RichProgressReporter:
|
|
101
|
+
"""Progress reporter using Rich's progress display.
|
|
102
|
+
|
|
103
|
+
This reporter creates a Rich Progress display with multiple tasks
|
|
104
|
+
corresponding to the phases of remeshing operations.
|
|
105
|
+
|
|
106
|
+
Examples
|
|
107
|
+
--------
|
|
108
|
+
>>> from mmgpy import MmgMesh3D
|
|
109
|
+
>>> from mmgpy.progress import RichProgressReporter
|
|
110
|
+
>>> mesh = MmgMesh3D(vertices, elements)
|
|
111
|
+
>>> with RichProgressReporter() as reporter:
|
|
112
|
+
... mesh.remesh(hmax=0.1, progress=reporter)
|
|
113
|
+
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
def __init__(self, *, transient: bool = True) -> None:
|
|
117
|
+
"""Initialize the Rich progress reporter.
|
|
118
|
+
|
|
119
|
+
Parameters
|
|
120
|
+
----------
|
|
121
|
+
transient : bool, default=True
|
|
122
|
+
If True, the progress display is removed after completion.
|
|
123
|
+
|
|
124
|
+
"""
|
|
125
|
+
self._transient = transient
|
|
126
|
+
self._progress = None
|
|
127
|
+
self._tasks: dict[str, Any] = {}
|
|
128
|
+
self._phase_names = {
|
|
129
|
+
"init": "Initializing",
|
|
130
|
+
"load": "Loading mesh",
|
|
131
|
+
"options": "Setting options",
|
|
132
|
+
"remesh": "Remeshing",
|
|
133
|
+
"save": "Saving mesh",
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
def __enter__(self) -> Self:
|
|
137
|
+
"""Start the progress display."""
|
|
138
|
+
from rich.progress import (
|
|
139
|
+
BarColumn,
|
|
140
|
+
Progress,
|
|
141
|
+
SpinnerColumn,
|
|
142
|
+
TextColumn,
|
|
143
|
+
TimeElapsedColumn,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
self._progress = Progress(
|
|
147
|
+
SpinnerColumn(),
|
|
148
|
+
TextColumn("[progress.description]{task.description}"),
|
|
149
|
+
BarColumn(),
|
|
150
|
+
TimeElapsedColumn(),
|
|
151
|
+
transient=self._transient,
|
|
152
|
+
)
|
|
153
|
+
self._progress.start()
|
|
154
|
+
return self
|
|
155
|
+
|
|
156
|
+
def __exit__(self, *args: object) -> None:
|
|
157
|
+
"""Stop the progress display."""
|
|
158
|
+
if self._progress is not None:
|
|
159
|
+
self._progress.stop()
|
|
160
|
+
|
|
161
|
+
def __call__(self, event: ProgressEvent) -> None:
|
|
162
|
+
"""Update the progress display with the event."""
|
|
163
|
+
if self._progress is None:
|
|
164
|
+
return
|
|
165
|
+
|
|
166
|
+
phase_desc = self._phase_names.get(event.phase, event.phase.capitalize())
|
|
167
|
+
|
|
168
|
+
if event.phase not in self._tasks:
|
|
169
|
+
task_id = self._progress.add_task(
|
|
170
|
+
description=phase_desc,
|
|
171
|
+
total=1.0 if event.status == "start" else None,
|
|
172
|
+
)
|
|
173
|
+
self._tasks[event.phase] = task_id
|
|
174
|
+
|
|
175
|
+
task_id = self._tasks[event.phase]
|
|
176
|
+
|
|
177
|
+
if event.status == "complete":
|
|
178
|
+
self._progress.update(task_id, completed=1.0, description=f"{phase_desc}")
|
|
179
|
+
elif event.status == "start":
|
|
180
|
+
self._progress.update(task_id, description=f"{phase_desc}...")
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@contextmanager
|
|
184
|
+
def rich_progress(
|
|
185
|
+
*,
|
|
186
|
+
transient: bool = True,
|
|
187
|
+
) -> Generator[ProgressCallback, None, None]:
|
|
188
|
+
"""Context manager for Rich progress display.
|
|
189
|
+
|
|
190
|
+
This is a convenience function for using Rich progress with remeshing.
|
|
191
|
+
|
|
192
|
+
Parameters
|
|
193
|
+
----------
|
|
194
|
+
transient : bool, default=True
|
|
195
|
+
If True, the progress display is removed after completion.
|
|
196
|
+
|
|
197
|
+
Yields
|
|
198
|
+
------
|
|
199
|
+
ProgressCallback
|
|
200
|
+
A progress callback function.
|
|
201
|
+
|
|
202
|
+
Examples
|
|
203
|
+
--------
|
|
204
|
+
>>> from mmgpy import MmgMesh3D
|
|
205
|
+
>>> from mmgpy.progress import rich_progress
|
|
206
|
+
>>> mesh = MmgMesh3D(vertices, elements)
|
|
207
|
+
>>> with rich_progress() as callback:
|
|
208
|
+
... mesh.remesh(hmax=0.1, progress=callback)
|
|
209
|
+
|
|
210
|
+
"""
|
|
211
|
+
from rich.progress import (
|
|
212
|
+
BarColumn,
|
|
213
|
+
Progress,
|
|
214
|
+
SpinnerColumn,
|
|
215
|
+
TextColumn,
|
|
216
|
+
TimeElapsedColumn,
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
phase_names = {
|
|
220
|
+
"init": "Initializing",
|
|
221
|
+
"load": "Loading mesh",
|
|
222
|
+
"options": "Setting options",
|
|
223
|
+
"remesh": "Remeshing",
|
|
224
|
+
"save": "Saving mesh",
|
|
225
|
+
}
|
|
226
|
+
tasks: dict[str, Any] = {}
|
|
227
|
+
|
|
228
|
+
with Progress(
|
|
229
|
+
SpinnerColumn(),
|
|
230
|
+
TextColumn("[progress.description]{task.description}"),
|
|
231
|
+
BarColumn(),
|
|
232
|
+
TimeElapsedColumn(),
|
|
233
|
+
transient=transient,
|
|
234
|
+
) as progress:
|
|
235
|
+
|
|
236
|
+
def callback(event: ProgressEvent) -> None:
|
|
237
|
+
phase_desc = phase_names.get(event.phase, event.phase.capitalize())
|
|
238
|
+
|
|
239
|
+
if event.phase not in tasks:
|
|
240
|
+
task_id = progress.add_task(
|
|
241
|
+
description=phase_desc,
|
|
242
|
+
total=1.0 if event.status == "start" else None,
|
|
243
|
+
)
|
|
244
|
+
tasks[event.phase] = task_id
|
|
245
|
+
|
|
246
|
+
task_id = tasks[event.phase]
|
|
247
|
+
|
|
248
|
+
if event.status == "complete":
|
|
249
|
+
progress.update(task_id, completed=1.0, description=f"{phase_desc}")
|
|
250
|
+
elif event.status == "start":
|
|
251
|
+
progress.update(task_id, description=f"{phase_desc}...")
|
|
252
|
+
|
|
253
|
+
yield callback
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def remesh_3d(
|
|
257
|
+
input_mesh: str | Path,
|
|
258
|
+
output_mesh: str | Path,
|
|
259
|
+
*,
|
|
260
|
+
input_sol: str | Path | None = None,
|
|
261
|
+
output_sol: str | Path | None = None,
|
|
262
|
+
progress: ProgressCallback | None = None,
|
|
263
|
+
**options: float,
|
|
264
|
+
) -> bool:
|
|
265
|
+
"""Remesh a 3D mesh with optional progress callback.
|
|
266
|
+
|
|
267
|
+
This is a wrapper around mmg3d.remesh that adds progress callback support.
|
|
268
|
+
|
|
269
|
+
Parameters
|
|
270
|
+
----------
|
|
271
|
+
input_mesh : str | Path
|
|
272
|
+
Path to the input mesh file.
|
|
273
|
+
output_mesh : str | Path
|
|
274
|
+
Path to the output mesh file.
|
|
275
|
+
input_sol : str | Path | None, optional
|
|
276
|
+
Path to the input solution file.
|
|
277
|
+
output_sol : str | Path | None, optional
|
|
278
|
+
Path to the output solution file.
|
|
279
|
+
progress : ProgressCallback | None, optional
|
|
280
|
+
Callback function to receive progress events.
|
|
281
|
+
**options
|
|
282
|
+
Additional options passed to mmg3d.remesh (hmin, hmax, hausd, etc.).
|
|
283
|
+
|
|
284
|
+
Returns
|
|
285
|
+
-------
|
|
286
|
+
bool
|
|
287
|
+
True if remeshing succeeded, False otherwise.
|
|
288
|
+
|
|
289
|
+
Examples
|
|
290
|
+
--------
|
|
291
|
+
>>> from mmgpy.progress import remesh_3d, rich_progress
|
|
292
|
+
>>> with rich_progress() as callback:
|
|
293
|
+
... remesh_3d("input.mesh", "output.mesh", hmax=0.1, progress=callback)
|
|
294
|
+
|
|
295
|
+
"""
|
|
296
|
+
from ._mmgpy import mmg3d
|
|
297
|
+
|
|
298
|
+
_emit_event(progress, "load", "start", "Loading input mesh")
|
|
299
|
+
_emit_event(progress, "options", "start", "Setting remesh options")
|
|
300
|
+
_emit_event(progress, "remesh", "start", "Starting remeshing")
|
|
301
|
+
|
|
302
|
+
result = mmg3d.remesh(
|
|
303
|
+
input_mesh=input_mesh,
|
|
304
|
+
input_sol=input_sol,
|
|
305
|
+
output_mesh=output_mesh,
|
|
306
|
+
output_sol=output_sol,
|
|
307
|
+
options=options,
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
_emit_event(
|
|
311
|
+
progress,
|
|
312
|
+
"remesh",
|
|
313
|
+
"complete",
|
|
314
|
+
"Remeshing complete",
|
|
315
|
+
{"success": result},
|
|
316
|
+
)
|
|
317
|
+
_emit_event(progress, "save", "complete", "Mesh saved")
|
|
318
|
+
|
|
319
|
+
return result
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def remesh_2d(
|
|
323
|
+
input_mesh: str | Path,
|
|
324
|
+
output_mesh: str | Path,
|
|
325
|
+
*,
|
|
326
|
+
input_sol: str | Path | None = None,
|
|
327
|
+
output_sol: str | Path | None = None,
|
|
328
|
+
progress: ProgressCallback | None = None,
|
|
329
|
+
**options: float,
|
|
330
|
+
) -> bool:
|
|
331
|
+
"""Remesh a 2D mesh with optional progress callback.
|
|
332
|
+
|
|
333
|
+
This is a wrapper around mmg2d.remesh that adds progress callback support.
|
|
334
|
+
|
|
335
|
+
Parameters
|
|
336
|
+
----------
|
|
337
|
+
input_mesh : str | Path
|
|
338
|
+
Path to the input mesh file.
|
|
339
|
+
output_mesh : str | Path
|
|
340
|
+
Path to the output mesh file.
|
|
341
|
+
input_sol : str | Path | None, optional
|
|
342
|
+
Path to the input solution file.
|
|
343
|
+
output_sol : str | Path | None, optional
|
|
344
|
+
Path to the output solution file.
|
|
345
|
+
progress : ProgressCallback | None, optional
|
|
346
|
+
Callback function to receive progress events.
|
|
347
|
+
**options
|
|
348
|
+
Additional options passed to mmg2d.remesh (hmin, hmax, hausd, etc.).
|
|
349
|
+
|
|
350
|
+
Returns
|
|
351
|
+
-------
|
|
352
|
+
bool
|
|
353
|
+
True if remeshing succeeded, False otherwise.
|
|
354
|
+
|
|
355
|
+
"""
|
|
356
|
+
from ._mmgpy import mmg2d
|
|
357
|
+
|
|
358
|
+
_emit_event(progress, "load", "start", "Loading input mesh")
|
|
359
|
+
_emit_event(progress, "options", "start", "Setting remesh options")
|
|
360
|
+
_emit_event(progress, "remesh", "start", "Starting remeshing")
|
|
361
|
+
|
|
362
|
+
result = mmg2d.remesh(
|
|
363
|
+
input_mesh=input_mesh,
|
|
364
|
+
input_sol=input_sol,
|
|
365
|
+
output_mesh=output_mesh,
|
|
366
|
+
output_sol=output_sol,
|
|
367
|
+
options=options,
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
_emit_event(
|
|
371
|
+
progress,
|
|
372
|
+
"remesh",
|
|
373
|
+
"complete",
|
|
374
|
+
"Remeshing complete",
|
|
375
|
+
{"success": result},
|
|
376
|
+
)
|
|
377
|
+
_emit_event(progress, "save", "complete", "Mesh saved")
|
|
378
|
+
|
|
379
|
+
return result
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def remesh_surface(
|
|
383
|
+
input_mesh: str | Path,
|
|
384
|
+
output_mesh: str | Path,
|
|
385
|
+
*,
|
|
386
|
+
input_sol: str | Path | None = None,
|
|
387
|
+
output_sol: str | Path | None = None,
|
|
388
|
+
progress: ProgressCallback | None = None,
|
|
389
|
+
**options: float,
|
|
390
|
+
) -> bool:
|
|
391
|
+
"""Remesh a surface mesh with optional progress callback.
|
|
392
|
+
|
|
393
|
+
This is a wrapper around mmgs.remesh that adds progress callback support.
|
|
394
|
+
|
|
395
|
+
Parameters
|
|
396
|
+
----------
|
|
397
|
+
input_mesh : str | Path
|
|
398
|
+
Path to the input mesh file.
|
|
399
|
+
output_mesh : str | Path
|
|
400
|
+
Path to the output mesh file.
|
|
401
|
+
input_sol : str | Path | None, optional
|
|
402
|
+
Path to the input solution file.
|
|
403
|
+
output_sol : str | Path | None, optional
|
|
404
|
+
Path to the output solution file.
|
|
405
|
+
progress : ProgressCallback | None, optional
|
|
406
|
+
Callback function to receive progress events.
|
|
407
|
+
**options
|
|
408
|
+
Additional options passed to mmgs.remesh (hmin, hmax, hausd, etc.).
|
|
409
|
+
|
|
410
|
+
Returns
|
|
411
|
+
-------
|
|
412
|
+
bool
|
|
413
|
+
True if remeshing succeeded, False otherwise.
|
|
414
|
+
|
|
415
|
+
"""
|
|
416
|
+
from ._mmgpy import mmgs
|
|
417
|
+
|
|
418
|
+
_emit_event(progress, "load", "start", "Loading input mesh")
|
|
419
|
+
_emit_event(progress, "options", "start", "Setting remesh options")
|
|
420
|
+
_emit_event(progress, "remesh", "start", "Starting remeshing")
|
|
421
|
+
|
|
422
|
+
result = mmgs.remesh(
|
|
423
|
+
input_mesh=input_mesh,
|
|
424
|
+
input_sol=input_sol,
|
|
425
|
+
output_mesh=output_mesh,
|
|
426
|
+
output_sol=output_sol,
|
|
427
|
+
options=options,
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
_emit_event(
|
|
431
|
+
progress,
|
|
432
|
+
"remesh",
|
|
433
|
+
"complete",
|
|
434
|
+
"Remeshing complete",
|
|
435
|
+
{"success": result},
|
|
436
|
+
)
|
|
437
|
+
_emit_event(progress, "save", "complete", "Mesh saved")
|
|
438
|
+
|
|
439
|
+
return result
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
def remesh_mesh(
|
|
443
|
+
mesh: MeshType,
|
|
444
|
+
*,
|
|
445
|
+
progress: ProgressCallback | None = None,
|
|
446
|
+
**options: float | bool | None,
|
|
447
|
+
) -> None:
|
|
448
|
+
"""Remesh an in-memory mesh with optional progress callback.
|
|
449
|
+
|
|
450
|
+
This is a wrapper around MmgMesh.remesh that adds progress callback support.
|
|
451
|
+
|
|
452
|
+
Parameters
|
|
453
|
+
----------
|
|
454
|
+
mesh : MmgMesh3D | MmgMesh2D | MmgMeshS
|
|
455
|
+
The mesh object to remesh.
|
|
456
|
+
progress : ProgressCallback | None, optional
|
|
457
|
+
Callback function to receive progress events.
|
|
458
|
+
**options
|
|
459
|
+
Additional options passed to mesh.remesh (hmin, hmax, hausd, etc.).
|
|
460
|
+
|
|
461
|
+
Examples
|
|
462
|
+
--------
|
|
463
|
+
>>> from mmgpy import MmgMesh3D
|
|
464
|
+
>>> from mmgpy.progress import remesh_mesh, rich_progress
|
|
465
|
+
>>> mesh = MmgMesh3D(vertices, elements)
|
|
466
|
+
>>> with rich_progress() as callback:
|
|
467
|
+
... remesh_mesh(mesh, hmax=0.1, progress=callback)
|
|
468
|
+
|
|
469
|
+
"""
|
|
470
|
+
_emit_event(progress, "init", "start", "Initializing mesh")
|
|
471
|
+
|
|
472
|
+
initial_vertices = len(mesh.get_vertices())
|
|
473
|
+
|
|
474
|
+
_emit_event(progress, "options", "start", "Setting remesh options")
|
|
475
|
+
_emit_event(progress, "remesh", "start", "Starting remeshing")
|
|
476
|
+
|
|
477
|
+
mesh.remesh(**options)
|
|
478
|
+
|
|
479
|
+
final_vertices = len(mesh.get_vertices())
|
|
480
|
+
|
|
481
|
+
_emit_event(
|
|
482
|
+
progress,
|
|
483
|
+
"remesh",
|
|
484
|
+
"complete",
|
|
485
|
+
"Remeshing complete",
|
|
486
|
+
{
|
|
487
|
+
"initial_vertices": initial_vertices,
|
|
488
|
+
"final_vertices": final_vertices,
|
|
489
|
+
"vertex_change": final_vertices - initial_vertices,
|
|
490
|
+
},
|
|
491
|
+
)
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
def remesh_mesh_lagrangian(
|
|
495
|
+
mesh: MeshType,
|
|
496
|
+
displacement: NDArray[np.float64],
|
|
497
|
+
*,
|
|
498
|
+
progress: ProgressCallback | None = None,
|
|
499
|
+
**options: float | bool | None,
|
|
500
|
+
) -> None:
|
|
501
|
+
"""Remesh an in-memory mesh with Lagrangian motion and progress callback.
|
|
502
|
+
|
|
503
|
+
This is a wrapper around MmgMesh.remesh_lagrangian that adds progress
|
|
504
|
+
callback support.
|
|
505
|
+
|
|
506
|
+
Parameters
|
|
507
|
+
----------
|
|
508
|
+
mesh : MmgMesh3D | MmgMesh2D | MmgMeshS
|
|
509
|
+
The mesh object to remesh.
|
|
510
|
+
displacement : NDArray[np.float64]
|
|
511
|
+
Displacement field for Lagrangian motion.
|
|
512
|
+
progress : ProgressCallback | None, optional
|
|
513
|
+
Callback function to receive progress events.
|
|
514
|
+
**options
|
|
515
|
+
Additional options passed to mesh.remesh_lagrangian.
|
|
516
|
+
|
|
517
|
+
"""
|
|
518
|
+
_emit_event(progress, "init", "start", "Initializing mesh")
|
|
519
|
+
|
|
520
|
+
initial_vertices = len(mesh.get_vertices())
|
|
521
|
+
|
|
522
|
+
_emit_event(progress, "options", "start", "Setting displacement field")
|
|
523
|
+
_emit_event(progress, "remesh", "start", "Starting Lagrangian remeshing")
|
|
524
|
+
|
|
525
|
+
mesh.remesh_lagrangian(displacement, **options)
|
|
526
|
+
|
|
527
|
+
final_vertices = len(mesh.get_vertices())
|
|
528
|
+
|
|
529
|
+
_emit_event(
|
|
530
|
+
progress,
|
|
531
|
+
"remesh",
|
|
532
|
+
"complete",
|
|
533
|
+
"Lagrangian remeshing complete",
|
|
534
|
+
{
|
|
535
|
+
"initial_vertices": initial_vertices,
|
|
536
|
+
"final_vertices": final_vertices,
|
|
537
|
+
"vertex_change": final_vertices - initial_vertices,
|
|
538
|
+
},
|
|
539
|
+
)
|