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.
Files changed (132) hide show
  1. bin/Release/mmg2d_O3.exe +0 -0
  2. bin/Release/mmg3d_O3.exe +0 -0
  3. bin/Release/mmgs_O3.exe +0 -0
  4. bin/__init__.py +10 -0
  5. bin/concrt140.dll +0 -0
  6. bin/mmg.dll +0 -0
  7. bin/mmg2d.dll +0 -0
  8. bin/mmg2d_O3.exe +0 -0
  9. bin/mmg3d.dll +0 -0
  10. bin/mmg3d_O3.exe +0 -0
  11. bin/mmgs.dll +0 -0
  12. bin/mmgs_O3.exe +0 -0
  13. bin/msvcp140.dll +0 -0
  14. bin/msvcp140_1.dll +0 -0
  15. bin/msvcp140_2.dll +0 -0
  16. bin/msvcp140_atomic_wait.dll +0 -0
  17. bin/msvcp140_codecvt_ids.dll +0 -0
  18. bin/vcruntime140.dll +0 -0
  19. bin/vcruntime140_1.dll +0 -0
  20. include/__init__.py +10 -0
  21. include/mmg/common/libmmgtypes.h +687 -0
  22. include/mmg/common/libmmgtypesf.h +762 -0
  23. include/mmg/common/mmg_export.h +47 -0
  24. include/mmg/common/mmgcmakedefines.h +46 -0
  25. include/mmg/common/mmgcmakedefinesf.h +29 -0
  26. include/mmg/common/mmgversion.h +54 -0
  27. include/mmg/libmmg.h +67 -0
  28. include/mmg/libmmgf.h +42 -0
  29. include/mmg/mmg2d/libmmg2d.h +2761 -0
  30. include/mmg/mmg2d/libmmg2df.h +3263 -0
  31. include/mmg/mmg2d/mmg2d_export.h +34 -0
  32. include/mmg/mmg3d/libmmg3d.h +3444 -0
  33. include/mmg/mmg3d/libmmg3df.h +4041 -0
  34. include/mmg/mmg3d/mmg3d_export.h +34 -0
  35. include/mmg/mmgs/libmmgs.h +2560 -0
  36. include/mmg/mmgs/libmmgsf.h +3028 -0
  37. include/mmg/mmgs/mmgs_export.h +34 -0
  38. lib/__init__.py +10 -0
  39. lib/cmake/mmg/FindElas.cmake +57 -0
  40. lib/cmake/mmg/FindSCOTCH.cmake +373 -0
  41. lib/cmake/mmg/MmgTargets-release.cmake +53 -0
  42. lib/cmake/mmg/MmgTargets.cmake +127 -0
  43. lib/cmake/mmg/mmgConfig.cmake +43 -0
  44. lib/mmg.lib +0 -0
  45. lib/mmg2d.lib +0 -0
  46. lib/mmg3d.lib +0 -0
  47. lib/mmgs.lib +0 -0
  48. mmgpy/__init__.py +888 -0
  49. mmgpy/_logging.py +86 -0
  50. mmgpy/_mmgpy.cp312-win_amd64.pyd +0 -0
  51. mmgpy/_mmgpy.pyi +650 -0
  52. mmgpy/_options.py +304 -0
  53. mmgpy/_progress.py +539 -0
  54. mmgpy/_pyvista.py +423 -0
  55. mmgpy/_version.py +3 -0
  56. mmgpy/_version.py.in +3 -0
  57. mmgpy/lagrangian.py +394 -0
  58. mmgpy/metrics.py +595 -0
  59. mmgpy/mmg2d.dll +0 -0
  60. mmgpy/mmg2d.lib +0 -0
  61. mmgpy/mmg3d.dll +0 -0
  62. mmgpy/mmg3d.lib +0 -0
  63. mmgpy/mmgs.dll +0 -0
  64. mmgpy/mmgs.lib +0 -0
  65. mmgpy/progress.py +57 -0
  66. mmgpy/py.typed +0 -0
  67. mmgpy/sizing.py +370 -0
  68. mmgpy-0.3.0.dist-info/DELVEWHEEL +2 -0
  69. mmgpy-0.3.0.dist-info/METADATA +75 -0
  70. mmgpy-0.3.0.dist-info/RECORD +132 -0
  71. mmgpy-0.3.0.dist-info/WHEEL +5 -0
  72. mmgpy-0.3.0.dist-info/entry_points.txt +6 -0
  73. mmgpy-0.3.0.dist-info/licenses/LICENSE +38 -0
  74. mmgpy.libs/vtkCommonColor-9.5-07cd19e9d77559cb8be83e8ac8833cd4.dll +0 -0
  75. mmgpy.libs/vtkCommonComputationalGeometry-9.5-4aaf997b087c330e171c14a4ba6be7b2.dll +0 -0
  76. mmgpy.libs/vtkCommonCore-9.5.dll +0 -0
  77. mmgpy.libs/vtkCommonDataModel-9.5.dll +0 -0
  78. mmgpy.libs/vtkCommonExecutionModel-9.5-2f7a1bae0a1d4d0e205eea43596a659c.dll +0 -0
  79. mmgpy.libs/vtkCommonMath-9.5-609b01246386fe29df2677fa5c7ca793.dll +0 -0
  80. mmgpy.libs/vtkCommonMisc-9.5-4173df33811eddea1529a40bf93266c8.dll +0 -0
  81. mmgpy.libs/vtkCommonSystem-9.5-e5b15bd84934b99e3b2bbe5d3e064c97.dll +0 -0
  82. mmgpy.libs/vtkCommonTransforms-9.5-9b76a61640718d893271cc0b5db50d1d.dll +0 -0
  83. mmgpy.libs/vtkDICOMParser-9.5-203c95a77d21799a8049a576e1b28f2e.dll +0 -0
  84. mmgpy.libs/vtkFiltersCellGrid-9.5-fa6bda61d2d528369d8b2f3a66d2d6b4.dll +0 -0
  85. mmgpy.libs/vtkFiltersCore-9.5-935a5f5225a975e99626296b2f3ded70.dll +0 -0
  86. mmgpy.libs/vtkFiltersExtraction-9.5-dc0a7543ba584f7e8ce9f9184485a228.dll +0 -0
  87. mmgpy.libs/vtkFiltersGeneral-9.5-709f69dbcca8aba1750582106a97c605.dll +0 -0
  88. mmgpy.libs/vtkFiltersGeometry-9.5-7abfb655763a62f56d63b45038d6e811.dll +0 -0
  89. mmgpy.libs/vtkFiltersHybrid-9.5-0721ec98d8a8b7442d900747e1ec59fb.dll +0 -0
  90. mmgpy.libs/vtkFiltersHyperTree-9.5-f9ee6a4761fdad8956c08a51dae77636.dll +0 -0
  91. mmgpy.libs/vtkFiltersModeling-9.5-458d9d2c544bb3c37de28c26c05c07bc.dll +0 -0
  92. mmgpy.libs/vtkFiltersParallel-9.5-1f243ffe308277c3970d8be4172d856f.dll +0 -0
  93. mmgpy.libs/vtkFiltersReduction-9.5-bf8c4a248bd84fbd6bb1a2ab5f646e56.dll +0 -0
  94. mmgpy.libs/vtkFiltersSources-9.5-492fa5b1b8562f4b141a347a38ae1ce5.dll +0 -0
  95. mmgpy.libs/vtkFiltersStatistics-9.5-6e99ef76387303ec5ff8c0fe6101d446.dll +0 -0
  96. mmgpy.libs/vtkFiltersTexture-9.5-15c23120b41b9a1c4acb01f790aad01f.dll +0 -0
  97. mmgpy.libs/vtkFiltersVerdict-9.5-332c0402a58129ec5b6af7b7f56cbb62.dll +0 -0
  98. mmgpy.libs/vtkIOCellGrid-9.5-88e1ec9c5a3554a82aedc0027fe84c6b.dll +0 -0
  99. mmgpy.libs/vtkIOCore-9.5.dll +0 -0
  100. mmgpy.libs/vtkIOGeometry-9.5-47c69db15c63c5773efa6851b59ae0a7.dll +0 -0
  101. mmgpy.libs/vtkIOImage-9.5-74bb92e688da5595ff9ff7645f9a0a13.dll +0 -0
  102. mmgpy.libs/vtkIOLegacy-9.5.dll +0 -0
  103. mmgpy.libs/vtkIOParallel-9.5.dll +0 -0
  104. mmgpy.libs/vtkIOParallelXML-9.5.dll +0 -0
  105. mmgpy.libs/vtkIOXML-9.5.dll +0 -0
  106. mmgpy.libs/vtkIOXMLParser-9.5-1893156c41fd4cf7165904675cb5d15d.dll +0 -0
  107. mmgpy.libs/vtkImagingCore-9.5-145fc0249cffbd27c610d10812e1cbfc.dll +0 -0
  108. mmgpy.libs/vtkImagingSources-9.5-f0c087a4669caa045584ed61f52502b7.dll +0 -0
  109. mmgpy.libs/vtkParallelCore-9.5-e91757b6dbd2a5369ab2bd05ff95d79d.dll +0 -0
  110. mmgpy.libs/vtkParallelDIY-9.5-04dd6b6b5dd8a5eacd43d270999cf09a.dll +0 -0
  111. mmgpy.libs/vtkRenderingCore-9.5-24a9802d77a083def26449fa681b1af7.dll +0 -0
  112. mmgpy.libs/vtkdoubleconversion-9.5-5e39712b9f4e44ea8a26e9119e53a7d4.dll +0 -0
  113. mmgpy.libs/vtkexpat-9.5-3b1dd25e09a2cccbbac723de448cb894.dll +0 -0
  114. mmgpy.libs/vtkfmt-9.5-50239b66bf315d100ecd306114139e9b.dll +0 -0
  115. mmgpy.libs/vtkjpeg-9.5-9412ee79f685a9196398b988a59666cd.dll +0 -0
  116. mmgpy.libs/vtkjsoncpp-9.5-abfad956527e3a4885dbb39f99f9e4d4.dll +0 -0
  117. mmgpy.libs/vtkkissfft-9.5-464db9175ce63de19addc69be524c4b7.dll +0 -0
  118. mmgpy.libs/vtkloguru-9.5-ec016ed005b4a79062e329ad8f1c382d.dll +0 -0
  119. mmgpy.libs/vtklz4-9.5-798b58f4518733b0eee8027eeba022fb.dll +0 -0
  120. mmgpy.libs/vtklzma-9.5-8f489b5430eb47d578de52c769a4dd5c.dll +0 -0
  121. mmgpy.libs/vtkmetaio-9.5-8f0a559399d53e4c7fc06272620b2167.dll +0 -0
  122. mmgpy.libs/vtkpng-9.5-1dbed3116ba7e31f56512a93b942cdf5.dll +0 -0
  123. mmgpy.libs/vtkpugixml-9.5-23ef37d65494ab52babc6d45b24764b7.dll +0 -0
  124. mmgpy.libs/vtksys-9.5.dll +0 -0
  125. mmgpy.libs/vtktiff-9.5-767fd93c8402517d5b2d1befab98c41e.dll +0 -0
  126. mmgpy.libs/vtktoken-9.5-f4ff567202eeb9a613c0b242aa05dbc9.dll +0 -0
  127. mmgpy.libs/vtkverdict-9.5-6bb84649d1b0ca1cc5454307fd35083b.dll +0 -0
  128. mmgpy.libs/vtkzlib-9.5-779937c44671e188e9f96125eb5afb12.dll +0 -0
  129. share/__init__.py +10 -0
  130. share/man/man1/mmg2d.1.gz +0 -0
  131. share/man/man1/mmg3d.1.gz +0 -0
  132. 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
+ )