mmgpy 0.5.0__cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.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 (109) hide show
  1. mmgpy/__init__.py +296 -0
  2. mmgpy/__main__.py +13 -0
  3. mmgpy/_io.py +535 -0
  4. mmgpy/_logging.py +290 -0
  5. mmgpy/_mesh.py +2286 -0
  6. mmgpy/_mmgpy.cpython-311-x86_64-linux-gnu.so +0 -0
  7. mmgpy/_mmgpy.pyi +2140 -0
  8. mmgpy/_options.py +304 -0
  9. mmgpy/_progress.py +850 -0
  10. mmgpy/_pyvista.py +410 -0
  11. mmgpy/_result.py +143 -0
  12. mmgpy/_transfer.py +273 -0
  13. mmgpy/_validation.py +669 -0
  14. mmgpy/_version.py +3 -0
  15. mmgpy/_version.py.in +3 -0
  16. mmgpy/bin/mmg2d_O3 +0 -0
  17. mmgpy/bin/mmg3d_O3 +0 -0
  18. mmgpy/bin/mmgs_O3 +0 -0
  19. mmgpy/interactive/__init__.py +24 -0
  20. mmgpy/interactive/sizing_editor.py +790 -0
  21. mmgpy/lagrangian.py +394 -0
  22. mmgpy/lib/libmmg2d.so +0 -0
  23. mmgpy/lib/libmmg2d.so.5 +0 -0
  24. mmgpy/lib/libmmg2d.so.5.8.0 +0 -0
  25. mmgpy/lib/libmmg3d.so +0 -0
  26. mmgpy/lib/libmmg3d.so.5 +0 -0
  27. mmgpy/lib/libmmg3d.so.5.8.0 +0 -0
  28. mmgpy/lib/libmmgs.so +0 -0
  29. mmgpy/lib/libmmgs.so.5 +0 -0
  30. mmgpy/lib/libmmgs.so.5.8.0 +0 -0
  31. mmgpy/lib/libvtkCommonColor-9.5.so.1 +0 -0
  32. mmgpy/lib/libvtkCommonComputationalGeometry-9.5.so.1 +0 -0
  33. mmgpy/lib/libvtkCommonCore-9.5.so.1 +0 -0
  34. mmgpy/lib/libvtkCommonDataModel-9.5.so.1 +0 -0
  35. mmgpy/lib/libvtkCommonExecutionModel-9.5.so.1 +0 -0
  36. mmgpy/lib/libvtkCommonMath-9.5.so.1 +0 -0
  37. mmgpy/lib/libvtkCommonMisc-9.5.so.1 +0 -0
  38. mmgpy/lib/libvtkCommonSystem-9.5.so.1 +0 -0
  39. mmgpy/lib/libvtkCommonTransforms-9.5.so.1 +0 -0
  40. mmgpy/lib/libvtkDICOMParser-9.5.so.1 +0 -0
  41. mmgpy/lib/libvtkFiltersCellGrid-9.5.so.1 +0 -0
  42. mmgpy/lib/libvtkFiltersCore-9.5.so.1 +0 -0
  43. mmgpy/lib/libvtkFiltersExtraction-9.5.so.1 +0 -0
  44. mmgpy/lib/libvtkFiltersGeneral-9.5.so.1 +0 -0
  45. mmgpy/lib/libvtkFiltersGeometry-9.5.so.1 +0 -0
  46. mmgpy/lib/libvtkFiltersHybrid-9.5.so.1 +0 -0
  47. mmgpy/lib/libvtkFiltersHyperTree-9.5.so.1 +0 -0
  48. mmgpy/lib/libvtkFiltersModeling-9.5.so.1 +0 -0
  49. mmgpy/lib/libvtkFiltersParallel-9.5.so.1 +0 -0
  50. mmgpy/lib/libvtkFiltersReduction-9.5.so.1 +0 -0
  51. mmgpy/lib/libvtkFiltersSources-9.5.so.1 +0 -0
  52. mmgpy/lib/libvtkFiltersStatistics-9.5.so.1 +0 -0
  53. mmgpy/lib/libvtkFiltersTexture-9.5.so.1 +0 -0
  54. mmgpy/lib/libvtkFiltersVerdict-9.5.so.1 +0 -0
  55. mmgpy/lib/libvtkIOCellGrid-9.5.so.1 +0 -0
  56. mmgpy/lib/libvtkIOCore-9.5.so.1 +0 -0
  57. mmgpy/lib/libvtkIOGeometry-9.5.so.1 +0 -0
  58. mmgpy/lib/libvtkIOImage-9.5.so.1 +0 -0
  59. mmgpy/lib/libvtkIOLegacy-9.5.so.1 +0 -0
  60. mmgpy/lib/libvtkIOParallel-9.5.so.1 +0 -0
  61. mmgpy/lib/libvtkIOParallelXML-9.5.so.1 +0 -0
  62. mmgpy/lib/libvtkIOXML-9.5.so.1 +0 -0
  63. mmgpy/lib/libvtkIOXMLParser-9.5.so.1 +0 -0
  64. mmgpy/lib/libvtkImagingCore-9.5.so.1 +0 -0
  65. mmgpy/lib/libvtkImagingSources-9.5.so.1 +0 -0
  66. mmgpy/lib/libvtkParallelCore-9.5.so.1 +0 -0
  67. mmgpy/lib/libvtkParallelDIY-9.5.so.1 +0 -0
  68. mmgpy/lib/libvtkRenderingCore-9.5.so.1 +0 -0
  69. mmgpy/lib/libvtkdoubleconversion-9.5.so.1 +0 -0
  70. mmgpy/lib/libvtkexpat-9.5.so.1 +0 -0
  71. mmgpy/lib/libvtkfmt-9.5.so.1 +0 -0
  72. mmgpy/lib/libvtkjpeg-9.5.so.1 +0 -0
  73. mmgpy/lib/libvtkjsoncpp-9.5.so.1 +0 -0
  74. mmgpy/lib/libvtkkissfft-9.5.so.1 +0 -0
  75. mmgpy/lib/libvtkloguru-9.5.so.1 +0 -0
  76. mmgpy/lib/libvtklz4-9.5.so.1 +0 -0
  77. mmgpy/lib/libvtklzma-9.5.so.1 +0 -0
  78. mmgpy/lib/libvtkmetaio-9.5.so.1 +0 -0
  79. mmgpy/lib/libvtkpng-9.5.so.1 +0 -0
  80. mmgpy/lib/libvtkpugixml-9.5.so.1 +0 -0
  81. mmgpy/lib/libvtksys-9.5.so.1 +0 -0
  82. mmgpy/lib/libvtktiff-9.5.so.1 +0 -0
  83. mmgpy/lib/libvtktoken-9.5.so.1 +0 -0
  84. mmgpy/lib/libvtkverdict-9.5.so.1 +0 -0
  85. mmgpy/lib/libvtkzlib-9.5.so.1 +0 -0
  86. mmgpy/metrics.py +596 -0
  87. mmgpy/progress.py +69 -0
  88. mmgpy/py.typed +0 -0
  89. mmgpy/repair/__init__.py +37 -0
  90. mmgpy/repair/_core.py +226 -0
  91. mmgpy/repair/_elements.py +241 -0
  92. mmgpy/repair/_vertices.py +219 -0
  93. mmgpy/sizing.py +370 -0
  94. mmgpy/ui/__init__.py +97 -0
  95. mmgpy/ui/__main__.py +87 -0
  96. mmgpy/ui/app.py +1837 -0
  97. mmgpy/ui/parsers.py +501 -0
  98. mmgpy/ui/remeshing.py +448 -0
  99. mmgpy/ui/samples.py +249 -0
  100. mmgpy/ui/utils.py +280 -0
  101. mmgpy/ui/viewer.py +587 -0
  102. mmgpy-0.5.0.dist-info/METADATA +186 -0
  103. mmgpy-0.5.0.dist-info/RECORD +109 -0
  104. mmgpy-0.5.0.dist-info/WHEEL +6 -0
  105. mmgpy-0.5.0.dist-info/entry_points.txt +13 -0
  106. mmgpy-0.5.0.dist-info/licenses/LICENSE +38 -0
  107. share/man/man1/mmg2d.1.gz +0 -0
  108. share/man/man1/mmg3d.1.gz +0 -0
  109. share/man/man1/mmgs.1.gz +0 -0
mmgpy/_mmgpy.pyi ADDED
@@ -0,0 +1,2140 @@
1
+ """Type stubs for the mmgpy C++ extension module.
2
+
3
+ This module provides type information for the pybind11 C++ bindings.
4
+ All element indices in this API are 0-based (Python convention), though
5
+ MMG internally uses 1-based indexing. The bindings handle this conversion.
6
+
7
+ Supported solution fields for set_field/get_field:
8
+ - "metric": Isotropic sizing field (Nx1 array)
9
+ - "displacement": Lagrangian motion field (Nx2 or Nx3 array)
10
+ - "levelset": Implicit surface definition (Nx1 array)
11
+ - "tensor": Anisotropic metric (Nx6 array, stored as xx, xy, xz, yy, yz, zz)
12
+ """
13
+
14
+ from pathlib import Path
15
+ from typing import Any, overload
16
+
17
+ import numpy as np
18
+ from numpy.typing import NDArray
19
+
20
+ MMG_VERSION: str
21
+
22
+ class mmg3d: # noqa: N801
23
+ """Static methods for file-based 3D mesh remeshing."""
24
+
25
+ @staticmethod
26
+ def remesh(
27
+ input_mesh: str | Path,
28
+ input_sol: str | Path | None = None,
29
+ output_mesh: str | Path | None = None,
30
+ output_sol: str | Path | None = None,
31
+ options: dict[str, float | int] | None = None,
32
+ ) -> bool:
33
+ """Remesh a 3D mesh file using MMG3D.
34
+
35
+ Parameters
36
+ ----------
37
+ input_mesh : str | Path
38
+ Path to input mesh file (.mesh format).
39
+ input_sol : str | Path | None
40
+ Path to input solution file (.sol format).
41
+ output_mesh : str | Path | None
42
+ Path for output mesh file. If None, modifies input in place.
43
+ output_sol : str | Path | None
44
+ Path for output solution file.
45
+ options : dict[str, float | int] | None
46
+ Remeshing options (hmin, hmax, hsiz, hausd, hgrad, verbose, etc.).
47
+
48
+ Returns
49
+ -------
50
+ bool
51
+ True if remeshing succeeded.
52
+
53
+ """
54
+
55
+ class mmg2d: # noqa: N801
56
+ """Static methods for file-based 2D mesh remeshing."""
57
+
58
+ @staticmethod
59
+ def remesh(
60
+ input_mesh: str | Path,
61
+ input_sol: str | Path | None = None,
62
+ output_mesh: str | Path | None = None,
63
+ output_sol: str | Path | None = None,
64
+ options: dict[str, float | int] | None = None,
65
+ ) -> bool:
66
+ """Remesh a 2D mesh file using MMG2D.
67
+
68
+ Parameters
69
+ ----------
70
+ input_mesh : str | Path
71
+ Path to input mesh file (.mesh format).
72
+ input_sol : str | Path | None
73
+ Path to input solution file (.sol format).
74
+ output_mesh : str | Path | None
75
+ Path for output mesh file. If None, modifies input in place.
76
+ output_sol : str | Path | None
77
+ Path for output solution file.
78
+ options : dict[str, float | int] | None
79
+ Remeshing options (hmin, hmax, hsiz, hausd, hgrad, verbose, etc.).
80
+
81
+ Returns
82
+ -------
83
+ bool
84
+ True if remeshing succeeded.
85
+
86
+ """
87
+
88
+ class mmgs: # noqa: N801
89
+ """Static methods for file-based surface mesh remeshing."""
90
+
91
+ @staticmethod
92
+ def remesh(
93
+ input_mesh: str | Path,
94
+ input_sol: str | Path | None = None,
95
+ output_mesh: str | Path | None = None,
96
+ output_sol: str | Path | None = None,
97
+ options: dict[str, float | int] | None = None,
98
+ ) -> bool:
99
+ """Remesh a surface mesh file using MMGS.
100
+
101
+ Parameters
102
+ ----------
103
+ input_mesh : str | Path
104
+ Path to input mesh file (.mesh format).
105
+ input_sol : str | Path | None
106
+ Path to input solution file (.sol format).
107
+ output_mesh : str | Path | None
108
+ Path for output mesh file. If None, modifies input in place.
109
+ output_sol : str | Path | None
110
+ Path for output solution file.
111
+ options : dict[str, float | int] | None
112
+ Remeshing options (hmin, hmax, hsiz, hausd, hgrad, verbose, etc.).
113
+
114
+ Returns
115
+ -------
116
+ bool
117
+ True if remeshing succeeded.
118
+
119
+ """
120
+
121
+ class MmgMesh3D:
122
+ """3D tetrahedral mesh class for in-memory remeshing.
123
+
124
+ All element indices in this class are 0-based (Python convention).
125
+ The underlying MMG library uses 1-based indexing, but the bindings
126
+ handle this conversion automatically.
127
+ """
128
+
129
+ @overload
130
+ def __init__(self) -> None:
131
+ """Create an empty 3D mesh."""
132
+
133
+ @overload
134
+ def __init__(
135
+ self,
136
+ vertices: NDArray[np.float64],
137
+ elements: NDArray[np.int32],
138
+ ) -> None:
139
+ """Create a 3D mesh from vertices and tetrahedra.
140
+
141
+ Parameters
142
+ ----------
143
+ vertices : NDArray[np.float64]
144
+ Vertex coordinates, shape (n_vertices, 3).
145
+ elements : NDArray[np.int32]
146
+ Tetrahedra connectivity, shape (n_tetrahedra, 4).
147
+
148
+ """
149
+
150
+ @overload
151
+ def __init__(
152
+ self,
153
+ filename: str | Path,
154
+ ) -> None:
155
+ """Load a 3D mesh from file.
156
+
157
+ Parameters
158
+ ----------
159
+ filename : str | Path
160
+ Path to mesh file (.mesh, .vtk, .vtu format).
161
+
162
+ """
163
+
164
+ def set_vertices_and_elements(
165
+ self,
166
+ vertices: NDArray[np.float64],
167
+ elements: NDArray[np.int32],
168
+ ) -> None:
169
+ """Set mesh vertices and tetrahedra.
170
+
171
+ Parameters
172
+ ----------
173
+ vertices : NDArray[np.float64]
174
+ Vertex coordinates, shape (n_vertices, 3).
175
+ elements : NDArray[np.int32]
176
+ Tetrahedra connectivity, shape (n_tetrahedra, 4).
177
+
178
+ """
179
+
180
+ def get_vertices(self) -> NDArray[np.float64]:
181
+ """Get vertex coordinates.
182
+
183
+ Returns
184
+ -------
185
+ NDArray[np.float64]
186
+ Vertex coordinates, shape (n_vertices, 3).
187
+
188
+ """
189
+
190
+ def get_elements(self) -> NDArray[np.int32]:
191
+ """Get tetrahedra connectivity (alias for get_tetrahedra).
192
+
193
+ Returns
194
+ -------
195
+ NDArray[np.int32]
196
+ Tetrahedra connectivity, shape (n_tetrahedra, 4).
197
+
198
+ """
199
+
200
+ def set_mesh_size(
201
+ self,
202
+ vertices: int = 0,
203
+ tetrahedra: int = 0,
204
+ prisms: int = 0,
205
+ triangles: int = 0,
206
+ quadrilaterals: int = 0,
207
+ edges: int = 0,
208
+ ) -> None:
209
+ """Allocate mesh storage for the specified element counts.
210
+
211
+ Call this before using single-element setters (set_vertex, etc.).
212
+
213
+ Parameters
214
+ ----------
215
+ vertices : int
216
+ Number of vertices.
217
+ tetrahedra : int
218
+ Number of tetrahedra.
219
+ prisms : int
220
+ Number of prisms.
221
+ triangles : int
222
+ Number of triangles (boundary faces).
223
+ quadrilaterals : int
224
+ Number of quadrilaterals.
225
+ edges : int
226
+ Number of edges.
227
+
228
+ """
229
+
230
+ def get_mesh_size(
231
+ self,
232
+ ) -> tuple[int, int, int, int, int, int]:
233
+ """Get current mesh element counts.
234
+
235
+ Returns
236
+ -------
237
+ tuple[int, int, int, int, int, int]
238
+ Tuple of (vertices, tetrahedra, prisms, triangles, quadrilaterals, edges).
239
+
240
+ """
241
+
242
+ def set_vertices(
243
+ self,
244
+ vertices: NDArray[np.float64],
245
+ refs: NDArray[np.int64] | None = None,
246
+ ) -> None:
247
+ """Set all vertex coordinates.
248
+
249
+ Parameters
250
+ ----------
251
+ vertices : NDArray[np.float64]
252
+ Vertex coordinates, shape (n_vertices, 3).
253
+ refs : NDArray[np.int64] | None
254
+ Reference markers for each vertex.
255
+
256
+ """
257
+
258
+ def set_tetrahedra(
259
+ self,
260
+ tetrahedra: NDArray[np.int32],
261
+ refs: NDArray[np.int64] | None = None,
262
+ ) -> None:
263
+ """Set all tetrahedra.
264
+
265
+ Parameters
266
+ ----------
267
+ tetrahedra : NDArray[np.int32]
268
+ Tetrahedra connectivity, shape (n_tetrahedra, 4).
269
+ refs : NDArray[np.int64] | None
270
+ Reference markers for each tetrahedron.
271
+
272
+ """
273
+
274
+ def set_triangles(
275
+ self,
276
+ triangles: NDArray[np.int32],
277
+ refs: NDArray[np.int64] | None = None,
278
+ ) -> None:
279
+ """Set all triangles (boundary faces).
280
+
281
+ Parameters
282
+ ----------
283
+ triangles : NDArray[np.int32]
284
+ Triangle connectivity, shape (n_triangles, 3).
285
+ refs : NDArray[np.int64] | None
286
+ Reference markers for each triangle.
287
+
288
+ """
289
+
290
+ def set_edges(
291
+ self,
292
+ edges: NDArray[np.int32],
293
+ refs: NDArray[np.int64] | None = None,
294
+ ) -> None:
295
+ """Set all edges.
296
+
297
+ Parameters
298
+ ----------
299
+ edges : NDArray[np.int32]
300
+ Edge connectivity, shape (n_edges, 2).
301
+ refs : NDArray[np.int64] | None
302
+ Reference markers for each edge.
303
+
304
+ """
305
+
306
+ def get_vertices_with_refs(
307
+ self,
308
+ ) -> tuple[NDArray[np.float64], NDArray[np.int64]]:
309
+ """Get vertex coordinates with reference markers.
310
+
311
+ Returns
312
+ -------
313
+ tuple[NDArray[np.float64], NDArray[np.int64]]
314
+ Tuple of (vertices, refs).
315
+
316
+ """
317
+
318
+ def get_triangles(self) -> NDArray[np.int32]:
319
+ """Get triangle connectivity.
320
+
321
+ Returns
322
+ -------
323
+ NDArray[np.int32]
324
+ Triangle connectivity, shape (n_triangles, 3).
325
+
326
+ """
327
+
328
+ def get_triangles_with_refs(
329
+ self,
330
+ ) -> tuple[NDArray[np.int32], NDArray[np.int64]]:
331
+ """Get triangle connectivity with reference markers.
332
+
333
+ Returns
334
+ -------
335
+ tuple[NDArray[np.int32], NDArray[np.int64]]
336
+ Tuple of (triangles, refs).
337
+
338
+ """
339
+
340
+ def get_elements_with_refs(
341
+ self,
342
+ ) -> tuple[NDArray[np.int32], NDArray[np.int64]]:
343
+ """Get tetrahedra connectivity with reference markers.
344
+
345
+ Returns
346
+ -------
347
+ tuple[NDArray[np.int32], NDArray[np.int64]]
348
+ Tuple of (tetrahedra, refs).
349
+
350
+ """
351
+
352
+ def get_edges(self) -> NDArray[np.int32]:
353
+ """Get edge connectivity.
354
+
355
+ Returns
356
+ -------
357
+ NDArray[np.int32]
358
+ Edge connectivity, shape (n_edges, 2).
359
+
360
+ """
361
+
362
+ def get_edges_with_refs(
363
+ self,
364
+ ) -> tuple[NDArray[np.int32], NDArray[np.int64]]:
365
+ """Get edge connectivity with reference markers.
366
+
367
+ Returns
368
+ -------
369
+ tuple[NDArray[np.int32], NDArray[np.int64]]
370
+ Tuple of (edges, refs).
371
+
372
+ """
373
+
374
+ def set_vertex(
375
+ self,
376
+ x: float,
377
+ y: float,
378
+ z: float,
379
+ ref: int,
380
+ idx: int,
381
+ ) -> None:
382
+ """Set a single vertex.
383
+
384
+ Parameters
385
+ ----------
386
+ x, y, z : float
387
+ Vertex coordinates.
388
+ ref : int
389
+ Reference marker.
390
+ idx : int
391
+ Vertex index (0-based).
392
+
393
+ """
394
+
395
+ def set_tetrahedron(
396
+ self,
397
+ v0: int,
398
+ v1: int,
399
+ v2: int,
400
+ v3: int,
401
+ ref: int,
402
+ idx: int,
403
+ ) -> None:
404
+ """Set a single tetrahedron.
405
+
406
+ Parameters
407
+ ----------
408
+ v0, v1, v2, v3 : int
409
+ Vertex indices (0-based).
410
+ ref : int
411
+ Reference marker.
412
+ idx : int
413
+ Tetrahedron index (0-based).
414
+
415
+ """
416
+
417
+ def set_triangle(
418
+ self,
419
+ v0: int,
420
+ v1: int,
421
+ v2: int,
422
+ ref: int,
423
+ idx: int,
424
+ ) -> None:
425
+ """Set a single triangle.
426
+
427
+ Parameters
428
+ ----------
429
+ v0, v1, v2 : int
430
+ Vertex indices (0-based).
431
+ ref : int
432
+ Reference marker.
433
+ idx : int
434
+ Triangle index (0-based).
435
+
436
+ """
437
+
438
+ def set_edge(self, v0: int, v1: int, ref: int, idx: int) -> None:
439
+ """Set a single edge.
440
+
441
+ Parameters
442
+ ----------
443
+ v0, v1 : int
444
+ Vertex indices (0-based).
445
+ ref : int
446
+ Reference marker.
447
+ idx : int
448
+ Edge index (0-based).
449
+
450
+ """
451
+
452
+ def get_vertex(self, idx: int) -> tuple[float, float, float, int]:
453
+ """Get a single vertex.
454
+
455
+ Parameters
456
+ ----------
457
+ idx : int
458
+ Vertex index (0-based).
459
+
460
+ Returns
461
+ -------
462
+ tuple[float, float, float, int]
463
+ Tuple of (x, y, z, ref).
464
+
465
+ """
466
+
467
+ def get_tetrahedron(
468
+ self,
469
+ idx: int,
470
+ ) -> tuple[int, int, int, int, int]:
471
+ """Get a single tetrahedron.
472
+
473
+ Parameters
474
+ ----------
475
+ idx : int
476
+ Tetrahedron index (0-based).
477
+
478
+ Returns
479
+ -------
480
+ tuple[int, int, int, int, int]
481
+ Tuple of (v0, v1, v2, v3, ref).
482
+
483
+ """
484
+
485
+ def get_triangle(self, idx: int) -> tuple[int, int, int, int]:
486
+ """Get a single triangle.
487
+
488
+ Parameters
489
+ ----------
490
+ idx : int
491
+ Triangle index (0-based).
492
+
493
+ Returns
494
+ -------
495
+ tuple[int, int, int, int]
496
+ Tuple of (v0, v1, v2, ref).
497
+
498
+ """
499
+
500
+ def get_edge(self, idx: int) -> tuple[int, int, int]:
501
+ """Get a single edge.
502
+
503
+ Parameters
504
+ ----------
505
+ idx : int
506
+ Edge index (0-based).
507
+
508
+ Returns
509
+ -------
510
+ tuple[int, int, int]
511
+ Tuple of (v0, v1, ref).
512
+
513
+ """
514
+
515
+ def set_corners(self, vertex_indices: NDArray[np.int32]) -> None:
516
+ """Mark vertices as corners (preserved during remeshing).
517
+
518
+ Parameters
519
+ ----------
520
+ vertex_indices : NDArray[np.int32]
521
+ Indices of corner vertices (0-based).
522
+
523
+ """
524
+
525
+ def set_required_vertices(self, vertex_indices: NDArray[np.int32]) -> None:
526
+ """Mark vertices as required (cannot be removed).
527
+
528
+ Parameters
529
+ ----------
530
+ vertex_indices : NDArray[np.int32]
531
+ Indices of required vertices (0-based).
532
+
533
+ """
534
+
535
+ def set_ridge_edges(self, edge_indices: NDArray[np.int32]) -> None:
536
+ """Mark edges as ridges (sharp features preserved).
537
+
538
+ Parameters
539
+ ----------
540
+ edge_indices : NDArray[np.int32]
541
+ Indices of ridge edges (0-based).
542
+
543
+ """
544
+
545
+ def get_adjacent_elements(self, idx: int) -> NDArray[np.int32]:
546
+ """Get indices of tetrahedra sharing faces with element idx.
547
+
548
+ Parameters
549
+ ----------
550
+ idx : int
551
+ Element index (0-based).
552
+
553
+ Returns
554
+ -------
555
+ NDArray[np.int32]
556
+ Array of 4 indices (-1 indicates boundary).
557
+
558
+ """
559
+
560
+ def get_vertex_neighbors(self, idx: int) -> NDArray[np.int32]:
561
+ """Get indices of vertices connected to vertex idx by an edge.
562
+
563
+ Parameters
564
+ ----------
565
+ idx : int
566
+ Vertex index (0-based).
567
+
568
+ Returns
569
+ -------
570
+ NDArray[np.int32]
571
+ Array of neighbor vertex indices.
572
+
573
+ """
574
+
575
+ def get_element_quality(self, idx: int) -> float:
576
+ """Get quality metric for a tetrahedron.
577
+
578
+ Parameters
579
+ ----------
580
+ idx : int
581
+ Tetrahedron index (0-based).
582
+
583
+ Returns
584
+ -------
585
+ float
586
+ Quality metric (0-1, higher is better).
587
+
588
+ """
589
+
590
+ def get_element_qualities(self) -> NDArray[np.float64]:
591
+ """Get quality metrics for all tetrahedra.
592
+
593
+ Returns
594
+ -------
595
+ NDArray[np.float64]
596
+ Quality metrics for all elements.
597
+
598
+ """
599
+
600
+ def set_prism(
601
+ self,
602
+ v0: int,
603
+ v1: int,
604
+ v2: int,
605
+ v3: int,
606
+ v4: int,
607
+ v5: int,
608
+ ref: int,
609
+ idx: int,
610
+ ) -> None:
611
+ """Set a single prism element.
612
+
613
+ Parameters
614
+ ----------
615
+ v0, v1, v2, v3, v4, v5 : int
616
+ Vertex indices (0-based).
617
+ ref : int
618
+ Reference marker.
619
+ idx : int
620
+ Prism index (0-based).
621
+
622
+ """
623
+
624
+ def set_quadrilateral(
625
+ self,
626
+ v0: int,
627
+ v1: int,
628
+ v2: int,
629
+ v3: int,
630
+ ref: int,
631
+ idx: int,
632
+ ) -> None:
633
+ """Set a single quadrilateral.
634
+
635
+ Parameters
636
+ ----------
637
+ v0, v1, v2, v3 : int
638
+ Vertex indices (0-based).
639
+ ref : int
640
+ Reference marker.
641
+ idx : int
642
+ Quadrilateral index (0-based).
643
+
644
+ """
645
+
646
+ def set_prisms(
647
+ self,
648
+ prisms: NDArray[np.int32],
649
+ refs: NDArray[np.int64] | None = None,
650
+ ) -> None:
651
+ """Set all prisms.
652
+
653
+ Parameters
654
+ ----------
655
+ prisms : NDArray[np.int32]
656
+ Prism connectivity, shape (n_prisms, 6).
657
+ refs : NDArray[np.int64] | None
658
+ Reference markers for each prism.
659
+
660
+ """
661
+
662
+ def set_quadrilaterals(
663
+ self,
664
+ quads: NDArray[np.int32],
665
+ refs: NDArray[np.int64] | None = None,
666
+ ) -> None:
667
+ """Set all quadrilaterals.
668
+
669
+ Parameters
670
+ ----------
671
+ quads : NDArray[np.int32]
672
+ Quadrilateral connectivity, shape (n_quads, 4).
673
+ refs : NDArray[np.int64] | None
674
+ Reference markers for each quadrilateral.
675
+
676
+ """
677
+
678
+ def get_prism(self, idx: int) -> tuple[int, int, int, int, int, int, int]:
679
+ """Get a single prism.
680
+
681
+ Parameters
682
+ ----------
683
+ idx : int
684
+ Prism index (0-based).
685
+
686
+ Returns
687
+ -------
688
+ tuple[int, int, int, int, int, int, int]
689
+ Tuple of (v0, v1, v2, v3, v4, v5, ref).
690
+
691
+ """
692
+
693
+ def get_quadrilateral(self, idx: int) -> tuple[int, int, int, int, int]:
694
+ """Get a single quadrilateral.
695
+
696
+ Parameters
697
+ ----------
698
+ idx : int
699
+ Quadrilateral index (0-based).
700
+
701
+ Returns
702
+ -------
703
+ tuple[int, int, int, int, int]
704
+ Tuple of (v0, v1, v2, v3, ref).
705
+
706
+ """
707
+
708
+ def get_prisms(self) -> NDArray[np.int32]:
709
+ """Get all prism connectivity.
710
+
711
+ Returns
712
+ -------
713
+ NDArray[np.int32]
714
+ Prism connectivity, shape (n_prisms, 6).
715
+
716
+ """
717
+
718
+ def get_prisms_with_refs(
719
+ self,
720
+ ) -> tuple[NDArray[np.int32], NDArray[np.int64]]:
721
+ """Get prism connectivity with reference markers.
722
+
723
+ Returns
724
+ -------
725
+ tuple[NDArray[np.int32], NDArray[np.int64]]
726
+ Tuple of (prisms, refs).
727
+
728
+ """
729
+
730
+ def get_quadrilaterals(self) -> NDArray[np.int32]:
731
+ """Get all quadrilateral connectivity.
732
+
733
+ Returns
734
+ -------
735
+ NDArray[np.int32]
736
+ Quadrilateral connectivity, shape (n_quads, 4).
737
+
738
+ """
739
+
740
+ def get_quadrilaterals_with_refs(
741
+ self,
742
+ ) -> tuple[NDArray[np.int32], NDArray[np.int64]]:
743
+ """Get quadrilateral connectivity with reference markers.
744
+
745
+ Returns
746
+ -------
747
+ tuple[NDArray[np.int32], NDArray[np.int64]]
748
+ Tuple of (quadrilaterals, refs).
749
+
750
+ """
751
+
752
+ def get_tetrahedra(self) -> NDArray[np.int32]:
753
+ """Get all tetrahedra connectivity.
754
+
755
+ Returns
756
+ -------
757
+ NDArray[np.int32]
758
+ Tetrahedra connectivity, shape (n_tetrahedra, 4).
759
+
760
+ """
761
+
762
+ def get_tetrahedra_with_refs(
763
+ self,
764
+ ) -> tuple[NDArray[np.int32], NDArray[np.int64]]:
765
+ """Get tetrahedra connectivity with reference markers.
766
+
767
+ Returns
768
+ -------
769
+ tuple[NDArray[np.int32], NDArray[np.int64]]
770
+ Tuple of (tetrahedra, refs).
771
+
772
+ """
773
+
774
+ def set_field(self, key: str, value: NDArray[np.float64]) -> None:
775
+ """Set a solution field on vertices.
776
+
777
+ Parameters
778
+ ----------
779
+ key : str
780
+ Field name: "metric", "displacement", "levelset", or "tensor".
781
+ value : NDArray[np.float64]
782
+ Field values (one row per vertex). Shape depends on field type:
783
+ - "metric": (n_vertices, 1) - isotropic sizing
784
+ - "displacement": (n_vertices, 3) - motion vectors
785
+ - "levelset": (n_vertices, 1) - signed distance
786
+ - "tensor": (n_vertices, 6) - anisotropic metric
787
+
788
+ """
789
+
790
+ def get_field(self, key: str) -> NDArray[np.float64]:
791
+ """Get a solution field from vertices.
792
+
793
+ Parameters
794
+ ----------
795
+ key : str
796
+ Field name: "metric", "displacement", "levelset", or "tensor".
797
+
798
+ Returns
799
+ -------
800
+ NDArray[np.float64]
801
+ Field values (one row per vertex).
802
+
803
+ """
804
+
805
+ def __setitem__(self, key: str, value: NDArray[np.float64]) -> None:
806
+ """Set a solution field using dictionary syntax.
807
+
808
+ Equivalent to set_field(key, value).
809
+ """
810
+
811
+ def __getitem__(self, key: str) -> NDArray[np.float64]:
812
+ """Get a solution field using dictionary syntax.
813
+
814
+ Equivalent to get_field(key).
815
+ """
816
+
817
+ def save(self, filename: str | Path) -> None:
818
+ """Save mesh to file.
819
+
820
+ Parameters
821
+ ----------
822
+ filename : str | Path
823
+ Output file path. Format determined by extension
824
+ (.mesh, .vtk, .vtu).
825
+
826
+ """
827
+
828
+ def remesh(
829
+ self,
830
+ *,
831
+ hmin: float | None = None,
832
+ hmax: float | None = None,
833
+ hsiz: float | None = None,
834
+ hausd: float | None = None,
835
+ hgrad: float | None = None,
836
+ verbose: int | bool | None = None,
837
+ optim: int | None = None,
838
+ noinsert: int | None = None,
839
+ noswap: int | None = None,
840
+ nomove: int | None = None,
841
+ nosurf: int | None = None,
842
+ **kwargs: float | None,
843
+ ) -> dict[str, Any]:
844
+ """Remesh the mesh in-place.
845
+
846
+ Parameters
847
+ ----------
848
+ hmin : float | None
849
+ Minimum edge size.
850
+ hmax : float | None
851
+ Maximum edge size.
852
+ hsiz : float | None
853
+ Uniform target edge size.
854
+ hausd : float | None
855
+ Hausdorff distance for geometry approximation.
856
+ hgrad : float | None
857
+ Gradation parameter (controls size transition).
858
+ verbose : int | bool | None
859
+ Verbosity level. True/False converted to 1/-1.
860
+ optim : int | None
861
+ Optimization mode (1 = optimize without topology changes).
862
+ noinsert : int | None
863
+ Disable vertex insertion (1 = disabled).
864
+ noswap : int | None
865
+ Disable edge/face swapping (1 = disabled).
866
+ nomove : int | None
867
+ Disable vertex relocation (1 = disabled).
868
+ nosurf : int | None
869
+ Disable surface modifications (1 = disabled).
870
+ **kwargs : float | int | None
871
+ Additional MMG options.
872
+
873
+ Returns
874
+ -------
875
+ dict[str, Any]
876
+ Statistics dictionary with before/after metrics.
877
+
878
+ """
879
+
880
+ def remesh_lagrangian(
881
+ self,
882
+ displacement: NDArray[np.float64],
883
+ *,
884
+ hmin: float | None = None,
885
+ hmax: float | None = None,
886
+ hsiz: float | None = None,
887
+ hausd: float | None = None,
888
+ hgrad: float | None = None,
889
+ verbose: int | bool | None = None,
890
+ lag: int | None = None,
891
+ **kwargs: float | None,
892
+ ) -> dict[str, Any]:
893
+ """Remesh following Lagrangian motion.
894
+
895
+ Moves the mesh according to a displacement field while
896
+ maintaining mesh quality.
897
+
898
+ Parameters
899
+ ----------
900
+ displacement : NDArray[np.float64]
901
+ Displacement vectors, shape (n_vertices, 3).
902
+ hmin : float | None
903
+ Minimum edge size.
904
+ hmax : float | None
905
+ Maximum edge size.
906
+ hsiz : float | None
907
+ Uniform target edge size.
908
+ hausd : float | None
909
+ Hausdorff distance for geometry approximation.
910
+ hgrad : float | None
911
+ Gradation parameter.
912
+ verbose : int | bool | None
913
+ Verbosity level.
914
+ lag : int | None
915
+ Lagrangian mode: 0=velocity, 1=displacement (default), 2=final position.
916
+ **kwargs : float | int | None
917
+ Additional MMG options.
918
+
919
+ Returns
920
+ -------
921
+ dict[str, Any]
922
+ Statistics dictionary with before/after metrics.
923
+
924
+ """
925
+
926
+ def remesh_levelset(
927
+ self,
928
+ levelset: NDArray[np.float64],
929
+ *,
930
+ ls: float | None = None,
931
+ hmin: float | None = None,
932
+ hmax: float | None = None,
933
+ hsiz: float | None = None,
934
+ hausd: float | None = None,
935
+ hgrad: float | None = None,
936
+ verbose: int | bool | None = None,
937
+ iso: int | None = None,
938
+ **kwargs: float | None,
939
+ ) -> dict[str, Any]:
940
+ """Remesh to conform to a level-set isosurface.
941
+
942
+ Discretizes the zero level-set (or specified isovalue) and
943
+ creates a mesh that conforms to this surface.
944
+
945
+ Parameters
946
+ ----------
947
+ levelset : NDArray[np.float64]
948
+ Level-set values, shape (n_vertices, 1).
949
+ ls : float | None
950
+ Isovalue to discretize (default 0.0).
951
+ hmin : float | None
952
+ Minimum edge size.
953
+ hmax : float | None
954
+ Maximum edge size.
955
+ hsiz : float | None
956
+ Uniform target edge size.
957
+ hausd : float | None
958
+ Hausdorff distance for geometry approximation.
959
+ hgrad : float | None
960
+ Gradation parameter.
961
+ verbose : int | bool | None
962
+ Verbosity level.
963
+ iso : int | None
964
+ Enable level-set mode (default 1).
965
+ **kwargs : float | int | None
966
+ Additional MMG options.
967
+
968
+ Returns
969
+ -------
970
+ dict[str, Any]
971
+ Statistics dictionary with before/after metrics.
972
+
973
+ """
974
+
975
+ class MmgMesh2D:
976
+ """2D triangular mesh class for in-memory remeshing.
977
+
978
+ All element indices in this class are 0-based (Python convention).
979
+ The underlying MMG library uses 1-based indexing, but the bindings
980
+ handle this conversion automatically.
981
+ """
982
+
983
+ @overload
984
+ def __init__(self) -> None:
985
+ """Create an empty 2D mesh."""
986
+
987
+ @overload
988
+ def __init__(
989
+ self,
990
+ vertices: NDArray[np.float64],
991
+ triangles: NDArray[np.int32],
992
+ ) -> None:
993
+ """Create a 2D mesh from vertices and triangles.
994
+
995
+ Parameters
996
+ ----------
997
+ vertices : NDArray[np.float64]
998
+ Vertex coordinates, shape (n_vertices, 2).
999
+ triangles : NDArray[np.int32]
1000
+ Triangle connectivity, shape (n_triangles, 3).
1001
+
1002
+ """
1003
+
1004
+ @overload
1005
+ def __init__(
1006
+ self,
1007
+ filename: str | Path,
1008
+ ) -> None:
1009
+ """Load a 2D mesh from file.
1010
+
1011
+ Parameters
1012
+ ----------
1013
+ filename : str | Path
1014
+ Path to mesh file (.mesh, .vtk, .vtu format).
1015
+
1016
+ """
1017
+
1018
+ def set_mesh_size(
1019
+ self,
1020
+ vertices: int = 0,
1021
+ triangles: int = 0,
1022
+ quadrilaterals: int = 0,
1023
+ edges: int = 0,
1024
+ ) -> None:
1025
+ """Allocate mesh storage for the specified element counts.
1026
+
1027
+ Parameters
1028
+ ----------
1029
+ vertices : int
1030
+ Number of vertices.
1031
+ triangles : int
1032
+ Number of triangles.
1033
+ quadrilaterals : int
1034
+ Number of quadrilaterals.
1035
+ edges : int
1036
+ Number of edges (boundary edges).
1037
+
1038
+ """
1039
+
1040
+ def get_mesh_size(self) -> tuple[int, int, int, int]:
1041
+ """Get current mesh element counts.
1042
+
1043
+ Returns
1044
+ -------
1045
+ tuple[int, int, int, int]
1046
+ Tuple of (vertices, triangles, quadrilaterals, edges).
1047
+
1048
+ """
1049
+
1050
+ def set_vertices(
1051
+ self,
1052
+ vertices: NDArray[np.float64],
1053
+ refs: NDArray[np.int64] | None = None,
1054
+ ) -> None:
1055
+ """Set all vertex coordinates.
1056
+
1057
+ Parameters
1058
+ ----------
1059
+ vertices : NDArray[np.float64]
1060
+ Vertex coordinates, shape (n_vertices, 2).
1061
+ refs : NDArray[np.int64] | None
1062
+ Reference markers for each vertex.
1063
+
1064
+ """
1065
+
1066
+ def set_triangles(
1067
+ self,
1068
+ triangles: NDArray[np.int32],
1069
+ refs: NDArray[np.int64] | None = None,
1070
+ ) -> None:
1071
+ """Set all triangles.
1072
+
1073
+ Parameters
1074
+ ----------
1075
+ triangles : NDArray[np.int32]
1076
+ Triangle connectivity, shape (n_triangles, 3).
1077
+ refs : NDArray[np.int64] | None
1078
+ Reference markers for each triangle.
1079
+
1080
+ """
1081
+
1082
+ def set_quadrilaterals(
1083
+ self,
1084
+ quads: NDArray[np.int32],
1085
+ refs: NDArray[np.int64] | None = None,
1086
+ ) -> None:
1087
+ """Set all quadrilaterals.
1088
+
1089
+ Parameters
1090
+ ----------
1091
+ quads : NDArray[np.int32]
1092
+ Quadrilateral connectivity, shape (n_quads, 4).
1093
+ refs : NDArray[np.int64] | None
1094
+ Reference markers for each quadrilateral.
1095
+
1096
+ """
1097
+
1098
+ def set_edges(
1099
+ self,
1100
+ edges: NDArray[np.int32],
1101
+ refs: NDArray[np.int64] | None = None,
1102
+ ) -> None:
1103
+ """Set all edges.
1104
+
1105
+ Parameters
1106
+ ----------
1107
+ edges : NDArray[np.int32]
1108
+ Edge connectivity, shape (n_edges, 2).
1109
+ refs : NDArray[np.int64] | None
1110
+ Reference markers for each edge.
1111
+
1112
+ """
1113
+
1114
+ def get_vertices(self) -> NDArray[np.float64]:
1115
+ """Get vertex coordinates.
1116
+
1117
+ Returns
1118
+ -------
1119
+ NDArray[np.float64]
1120
+ Vertex coordinates, shape (n_vertices, 2).
1121
+
1122
+ """
1123
+
1124
+ def get_vertices_with_refs(
1125
+ self,
1126
+ ) -> tuple[NDArray[np.float64], NDArray[np.int64]]:
1127
+ """Get vertex coordinates with reference markers.
1128
+
1129
+ Returns
1130
+ -------
1131
+ tuple[NDArray[np.float64], NDArray[np.int64]]
1132
+ Tuple of (vertices, refs).
1133
+
1134
+ """
1135
+
1136
+ def get_triangles(self) -> NDArray[np.int32]:
1137
+ """Get triangle connectivity.
1138
+
1139
+ Returns
1140
+ -------
1141
+ NDArray[np.int32]
1142
+ Triangle connectivity, shape (n_triangles, 3).
1143
+
1144
+ """
1145
+
1146
+ def get_triangles_with_refs(
1147
+ self,
1148
+ ) -> tuple[NDArray[np.int32], NDArray[np.int64]]:
1149
+ """Get triangle connectivity with reference markers.
1150
+
1151
+ Returns
1152
+ -------
1153
+ tuple[NDArray[np.int32], NDArray[np.int64]]
1154
+ Tuple of (triangles, refs).
1155
+
1156
+ """
1157
+
1158
+ def get_quadrilaterals(self) -> NDArray[np.int32]:
1159
+ """Get quadrilateral connectivity.
1160
+
1161
+ Returns
1162
+ -------
1163
+ NDArray[np.int32]
1164
+ Quadrilateral connectivity, shape (n_quads, 4).
1165
+
1166
+ """
1167
+
1168
+ def get_quadrilaterals_with_refs(
1169
+ self,
1170
+ ) -> tuple[NDArray[np.int32], NDArray[np.int64]]:
1171
+ """Get quadrilateral connectivity with reference markers.
1172
+
1173
+ Returns
1174
+ -------
1175
+ tuple[NDArray[np.int32], NDArray[np.int64]]
1176
+ Tuple of (quadrilaterals, refs).
1177
+
1178
+ """
1179
+
1180
+ def get_edges(self) -> NDArray[np.int32]:
1181
+ """Get edge connectivity.
1182
+
1183
+ Returns
1184
+ -------
1185
+ NDArray[np.int32]
1186
+ Edge connectivity, shape (n_edges, 2).
1187
+
1188
+ """
1189
+
1190
+ def get_edges_with_refs(
1191
+ self,
1192
+ ) -> tuple[NDArray[np.int32], NDArray[np.int64]]:
1193
+ """Get edge connectivity with reference markers.
1194
+
1195
+ Returns
1196
+ -------
1197
+ tuple[NDArray[np.int32], NDArray[np.int64]]
1198
+ Tuple of (edges, refs).
1199
+
1200
+ """
1201
+
1202
+ def set_vertex(self, x: float, y: float, ref: int, idx: int) -> None:
1203
+ """Set a single vertex.
1204
+
1205
+ Parameters
1206
+ ----------
1207
+ x, y : float
1208
+ Vertex coordinates.
1209
+ ref : int
1210
+ Reference marker.
1211
+ idx : int
1212
+ Vertex index (0-based).
1213
+
1214
+ """
1215
+
1216
+ def set_triangle(
1217
+ self,
1218
+ v0: int,
1219
+ v1: int,
1220
+ v2: int,
1221
+ ref: int,
1222
+ idx: int,
1223
+ ) -> None:
1224
+ """Set a single triangle.
1225
+
1226
+ Parameters
1227
+ ----------
1228
+ v0, v1, v2 : int
1229
+ Vertex indices (0-based).
1230
+ ref : int
1231
+ Reference marker.
1232
+ idx : int
1233
+ Triangle index (0-based).
1234
+
1235
+ """
1236
+
1237
+ def set_quadrilateral(
1238
+ self,
1239
+ v0: int,
1240
+ v1: int,
1241
+ v2: int,
1242
+ v3: int,
1243
+ ref: int,
1244
+ idx: int,
1245
+ ) -> None:
1246
+ """Set a single quadrilateral.
1247
+
1248
+ Parameters
1249
+ ----------
1250
+ v0, v1, v2, v3 : int
1251
+ Vertex indices (0-based).
1252
+ ref : int
1253
+ Reference marker.
1254
+ idx : int
1255
+ Quadrilateral index (0-based).
1256
+
1257
+ """
1258
+
1259
+ def set_edge(self, v0: int, v1: int, ref: int, idx: int) -> None:
1260
+ """Set a single edge.
1261
+
1262
+ Parameters
1263
+ ----------
1264
+ v0, v1 : int
1265
+ Vertex indices (0-based).
1266
+ ref : int
1267
+ Reference marker.
1268
+ idx : int
1269
+ Edge index (0-based).
1270
+
1271
+ """
1272
+
1273
+ def get_vertex(self, idx: int) -> tuple[float, float, int]:
1274
+ """Get a single vertex.
1275
+
1276
+ Parameters
1277
+ ----------
1278
+ idx : int
1279
+ Vertex index (0-based).
1280
+
1281
+ Returns
1282
+ -------
1283
+ tuple[float, float, int]
1284
+ Tuple of (x, y, ref).
1285
+
1286
+ """
1287
+
1288
+ def get_triangle(self, idx: int) -> tuple[int, int, int, int]:
1289
+ """Get a single triangle.
1290
+
1291
+ Parameters
1292
+ ----------
1293
+ idx : int
1294
+ Triangle index (0-based).
1295
+
1296
+ Returns
1297
+ -------
1298
+ tuple[int, int, int, int]
1299
+ Tuple of (v0, v1, v2, ref).
1300
+
1301
+ """
1302
+
1303
+ def get_quadrilateral(self, idx: int) -> tuple[int, int, int, int, int]:
1304
+ """Get a single quadrilateral.
1305
+
1306
+ Parameters
1307
+ ----------
1308
+ idx : int
1309
+ Quadrilateral index (0-based).
1310
+
1311
+ Returns
1312
+ -------
1313
+ tuple[int, int, int, int, int]
1314
+ Tuple of (v0, v1, v2, v3, ref).
1315
+
1316
+ """
1317
+
1318
+ def get_edge(self, idx: int) -> tuple[int, int, int]:
1319
+ """Get a single edge.
1320
+
1321
+ Parameters
1322
+ ----------
1323
+ idx : int
1324
+ Edge index (0-based).
1325
+
1326
+ Returns
1327
+ -------
1328
+ tuple[int, int, int]
1329
+ Tuple of (v0, v1, ref).
1330
+
1331
+ """
1332
+
1333
+ def set_corners(self, vertex_indices: NDArray[np.int32]) -> None:
1334
+ """Mark vertices as corners (preserved during remeshing).
1335
+
1336
+ Parameters
1337
+ ----------
1338
+ vertex_indices : NDArray[np.int32]
1339
+ Indices of corner vertices (0-based).
1340
+
1341
+ """
1342
+
1343
+ def set_required_vertices(self, vertex_indices: NDArray[np.int32]) -> None:
1344
+ """Mark vertices as required (cannot be removed).
1345
+
1346
+ Parameters
1347
+ ----------
1348
+ vertex_indices : NDArray[np.int32]
1349
+ Indices of required vertices (0-based).
1350
+
1351
+ """
1352
+
1353
+ def set_required_edges(self, edge_indices: NDArray[np.int32]) -> None:
1354
+ """Mark edges as required (cannot be modified).
1355
+
1356
+ Parameters
1357
+ ----------
1358
+ edge_indices : NDArray[np.int32]
1359
+ Indices of required edges (0-based).
1360
+
1361
+ """
1362
+
1363
+ def get_adjacent_elements(self, idx: int) -> NDArray[np.int32]:
1364
+ """Get indices of triangles sharing edges with element idx.
1365
+
1366
+ Parameters
1367
+ ----------
1368
+ idx : int
1369
+ Element index (0-based).
1370
+
1371
+ Returns
1372
+ -------
1373
+ NDArray[np.int32]
1374
+ Array of 3 indices (-1 indicates boundary).
1375
+
1376
+ """
1377
+
1378
+ def get_vertex_neighbors(self, idx: int) -> NDArray[np.int32]:
1379
+ """Get indices of vertices connected to vertex idx by an edge.
1380
+
1381
+ Parameters
1382
+ ----------
1383
+ idx : int
1384
+ Vertex index (0-based).
1385
+
1386
+ Returns
1387
+ -------
1388
+ NDArray[np.int32]
1389
+ Array of neighbor vertex indices.
1390
+
1391
+ """
1392
+
1393
+ def get_element_quality(self, idx: int) -> float:
1394
+ """Get quality metric for a triangle.
1395
+
1396
+ Parameters
1397
+ ----------
1398
+ idx : int
1399
+ Triangle index (0-based).
1400
+
1401
+ Returns
1402
+ -------
1403
+ float
1404
+ Quality metric (0-1, higher is better).
1405
+
1406
+ """
1407
+
1408
+ def get_element_qualities(self) -> NDArray[np.float64]:
1409
+ """Get quality metrics for all triangles.
1410
+
1411
+ Returns
1412
+ -------
1413
+ NDArray[np.float64]
1414
+ Quality metrics for all elements.
1415
+
1416
+ """
1417
+
1418
+ def set_field(self, key: str, value: NDArray[np.float64]) -> None:
1419
+ """Set a solution field on vertices.
1420
+
1421
+ Parameters
1422
+ ----------
1423
+ key : str
1424
+ Field name: "metric", "displacement", "levelset", or "tensor".
1425
+ value : NDArray[np.float64]
1426
+ Field values (one row per vertex).
1427
+
1428
+ """
1429
+
1430
+ def get_field(self, key: str) -> NDArray[np.float64]:
1431
+ """Get a solution field from vertices.
1432
+
1433
+ Parameters
1434
+ ----------
1435
+ key : str
1436
+ Field name.
1437
+
1438
+ Returns
1439
+ -------
1440
+ NDArray[np.float64]
1441
+ Field values (one row per vertex).
1442
+
1443
+ """
1444
+
1445
+ def __setitem__(self, key: str, value: NDArray[np.float64]) -> None:
1446
+ """Set a solution field using dictionary syntax."""
1447
+
1448
+ def __getitem__(self, key: str) -> NDArray[np.float64]:
1449
+ """Get a solution field using dictionary syntax."""
1450
+
1451
+ def save(self, filename: str | Path) -> None:
1452
+ """Save mesh to file.
1453
+
1454
+ Parameters
1455
+ ----------
1456
+ filename : str | Path
1457
+ Output file path. Format determined by extension.
1458
+
1459
+ """
1460
+
1461
+ def remesh(
1462
+ self,
1463
+ *,
1464
+ hmin: float | None = None,
1465
+ hmax: float | None = None,
1466
+ hsiz: float | None = None,
1467
+ hausd: float | None = None,
1468
+ hgrad: float | None = None,
1469
+ verbose: int | bool | None = None,
1470
+ optim: int | None = None,
1471
+ noinsert: int | None = None,
1472
+ noswap: int | None = None,
1473
+ nomove: int | None = None,
1474
+ **kwargs: float | None,
1475
+ ) -> dict[str, Any]:
1476
+ """Remesh the mesh in-place.
1477
+
1478
+ Parameters
1479
+ ----------
1480
+ hmin : float | None
1481
+ Minimum edge size.
1482
+ hmax : float | None
1483
+ Maximum edge size.
1484
+ hsiz : float | None
1485
+ Uniform target edge size.
1486
+ hausd : float | None
1487
+ Hausdorff distance for geometry approximation.
1488
+ hgrad : float | None
1489
+ Gradation parameter.
1490
+ verbose : int | bool | None
1491
+ Verbosity level. True/False converted to 1/-1.
1492
+ optim : int | None
1493
+ Optimization mode.
1494
+ noinsert : int | None
1495
+ Disable vertex insertion.
1496
+ noswap : int | None
1497
+ Disable edge swapping.
1498
+ nomove : int | None
1499
+ Disable vertex relocation.
1500
+ **kwargs : float | int | None
1501
+ Additional MMG options.
1502
+
1503
+ Returns
1504
+ -------
1505
+ dict[str, Any]
1506
+ Statistics dictionary with before/after metrics.
1507
+
1508
+ """
1509
+
1510
+ def remesh_lagrangian(
1511
+ self,
1512
+ displacement: NDArray[np.float64],
1513
+ *,
1514
+ hmin: float | None = None,
1515
+ hmax: float | None = None,
1516
+ hsiz: float | None = None,
1517
+ hausd: float | None = None,
1518
+ hgrad: float | None = None,
1519
+ verbose: int | bool | None = None,
1520
+ lag: int | None = None,
1521
+ **kwargs: float | None,
1522
+ ) -> dict[str, Any]:
1523
+ """Remesh following Lagrangian motion.
1524
+
1525
+ Parameters
1526
+ ----------
1527
+ displacement : NDArray[np.float64]
1528
+ Displacement vectors, shape (n_vertices, 2).
1529
+ hmin : float | None
1530
+ Minimum edge size.
1531
+ hmax : float | None
1532
+ Maximum edge size.
1533
+ hsiz : float | None
1534
+ Uniform target edge size.
1535
+ hausd : float | None
1536
+ Hausdorff distance for geometry approximation.
1537
+ hgrad : float | None
1538
+ Gradation parameter.
1539
+ verbose : int | bool | None
1540
+ Verbosity level.
1541
+ lag : int | None
1542
+ Lagrangian mode: 0=velocity, 1=displacement (default), 2=final position.
1543
+ **kwargs : float | int | None
1544
+ Additional MMG options.
1545
+
1546
+ Returns
1547
+ -------
1548
+ dict[str, Any]
1549
+ Statistics dictionary with before/after metrics.
1550
+
1551
+ """
1552
+
1553
+ def remesh_levelset(
1554
+ self,
1555
+ levelset: NDArray[np.float64],
1556
+ *,
1557
+ ls: float | None = None,
1558
+ hmin: float | None = None,
1559
+ hmax: float | None = None,
1560
+ hsiz: float | None = None,
1561
+ hausd: float | None = None,
1562
+ hgrad: float | None = None,
1563
+ verbose: int | bool | None = None,
1564
+ iso: int | None = None,
1565
+ **kwargs: float | None,
1566
+ ) -> dict[str, Any]:
1567
+ """Remesh to conform to a level-set isoline.
1568
+
1569
+ Parameters
1570
+ ----------
1571
+ levelset : NDArray[np.float64]
1572
+ Level-set values, shape (n_vertices, 1).
1573
+ ls : float | None
1574
+ Isovalue to discretize (default 0.0).
1575
+ hmin : float | None
1576
+ Minimum edge size.
1577
+ hmax : float | None
1578
+ Maximum edge size.
1579
+ hsiz : float | None
1580
+ Uniform target edge size.
1581
+ hausd : float | None
1582
+ Hausdorff distance for geometry approximation.
1583
+ hgrad : float | None
1584
+ Gradation parameter.
1585
+ verbose : int | bool | None
1586
+ Verbosity level.
1587
+ iso : int | None
1588
+ Enable level-set mode (default 1).
1589
+ **kwargs : float | int | None
1590
+ Additional MMG options.
1591
+
1592
+ Returns
1593
+ -------
1594
+ dict[str, Any]
1595
+ Statistics dictionary with before/after metrics.
1596
+
1597
+ """
1598
+
1599
+ class MmgMeshS:
1600
+ """Surface mesh class for in-memory remeshing.
1601
+
1602
+ All element indices in this class are 0-based (Python convention).
1603
+ The underlying MMG library uses 1-based indexing, but the bindings
1604
+ handle this conversion automatically.
1605
+
1606
+ Note: MmgMeshS does not support Lagrangian remeshing (remesh_lagrangian).
1607
+ """
1608
+
1609
+ @overload
1610
+ def __init__(self) -> None:
1611
+ """Create an empty surface mesh."""
1612
+
1613
+ @overload
1614
+ def __init__(
1615
+ self,
1616
+ vertices: NDArray[np.float64],
1617
+ triangles: NDArray[np.int32],
1618
+ ) -> None:
1619
+ """Create a surface mesh from vertices and triangles.
1620
+
1621
+ Parameters
1622
+ ----------
1623
+ vertices : NDArray[np.float64]
1624
+ Vertex coordinates, shape (n_vertices, 3).
1625
+ triangles : NDArray[np.int32]
1626
+ Triangle connectivity, shape (n_triangles, 3).
1627
+
1628
+ """
1629
+
1630
+ @overload
1631
+ def __init__(
1632
+ self,
1633
+ filename: str | Path,
1634
+ ) -> None:
1635
+ """Load a surface mesh from file.
1636
+
1637
+ Parameters
1638
+ ----------
1639
+ filename : str | Path
1640
+ Path to mesh file (.mesh, .vtk, .vtu format).
1641
+
1642
+ """
1643
+
1644
+ def set_mesh_size(
1645
+ self,
1646
+ vertices: int = 0,
1647
+ triangles: int = 0,
1648
+ edges: int = 0,
1649
+ ) -> None:
1650
+ """Allocate mesh storage for the specified element counts.
1651
+
1652
+ Parameters
1653
+ ----------
1654
+ vertices : int
1655
+ Number of vertices.
1656
+ triangles : int
1657
+ Number of triangles.
1658
+ edges : int
1659
+ Number of edges.
1660
+
1661
+ """
1662
+
1663
+ def get_mesh_size(self) -> tuple[int, int, int]:
1664
+ """Get current mesh element counts.
1665
+
1666
+ Returns
1667
+ -------
1668
+ tuple[int, int, int]
1669
+ Tuple of (vertices, triangles, edges).
1670
+
1671
+ """
1672
+
1673
+ def set_vertices(
1674
+ self,
1675
+ vertices: NDArray[np.float64],
1676
+ refs: NDArray[np.int64] | None = None,
1677
+ ) -> None:
1678
+ """Set all vertex coordinates.
1679
+
1680
+ Parameters
1681
+ ----------
1682
+ vertices : NDArray[np.float64]
1683
+ Vertex coordinates, shape (n_vertices, 3).
1684
+ refs : NDArray[np.int64] | None
1685
+ Reference markers for each vertex.
1686
+
1687
+ """
1688
+
1689
+ def set_triangles(
1690
+ self,
1691
+ triangles: NDArray[np.int32],
1692
+ refs: NDArray[np.int64] | None = None,
1693
+ ) -> None:
1694
+ """Set all triangles.
1695
+
1696
+ Parameters
1697
+ ----------
1698
+ triangles : NDArray[np.int32]
1699
+ Triangle connectivity, shape (n_triangles, 3).
1700
+ refs : NDArray[np.int64] | None
1701
+ Reference markers for each triangle.
1702
+
1703
+ """
1704
+
1705
+ def set_edges(
1706
+ self,
1707
+ edges: NDArray[np.int32],
1708
+ refs: NDArray[np.int64] | None = None,
1709
+ ) -> None:
1710
+ """Set all edges.
1711
+
1712
+ Parameters
1713
+ ----------
1714
+ edges : NDArray[np.int32]
1715
+ Edge connectivity, shape (n_edges, 2).
1716
+ refs : NDArray[np.int64] | None
1717
+ Reference markers for each edge.
1718
+
1719
+ """
1720
+
1721
+ def get_vertices(self) -> NDArray[np.float64]:
1722
+ """Get vertex coordinates.
1723
+
1724
+ Returns
1725
+ -------
1726
+ NDArray[np.float64]
1727
+ Vertex coordinates, shape (n_vertices, 3).
1728
+
1729
+ """
1730
+
1731
+ def get_vertices_with_refs(
1732
+ self,
1733
+ ) -> tuple[NDArray[np.float64], NDArray[np.int64]]:
1734
+ """Get vertex coordinates with reference markers.
1735
+
1736
+ Returns
1737
+ -------
1738
+ tuple[NDArray[np.float64], NDArray[np.int64]]
1739
+ Tuple of (vertices, refs).
1740
+
1741
+ """
1742
+
1743
+ def get_triangles(self) -> NDArray[np.int32]:
1744
+ """Get triangle connectivity.
1745
+
1746
+ Returns
1747
+ -------
1748
+ NDArray[np.int32]
1749
+ Triangle connectivity, shape (n_triangles, 3).
1750
+
1751
+ """
1752
+
1753
+ def get_triangles_with_refs(
1754
+ self,
1755
+ ) -> tuple[NDArray[np.int32], NDArray[np.int64]]:
1756
+ """Get triangle connectivity with reference markers.
1757
+
1758
+ Returns
1759
+ -------
1760
+ tuple[NDArray[np.int32], NDArray[np.int64]]
1761
+ Tuple of (triangles, refs).
1762
+
1763
+ """
1764
+
1765
+ def get_edges(self) -> NDArray[np.int32]:
1766
+ """Get edge connectivity.
1767
+
1768
+ Returns
1769
+ -------
1770
+ NDArray[np.int32]
1771
+ Edge connectivity, shape (n_edges, 2).
1772
+
1773
+ """
1774
+
1775
+ def get_edges_with_refs(
1776
+ self,
1777
+ ) -> tuple[NDArray[np.int32], NDArray[np.int64]]:
1778
+ """Get edge connectivity with reference markers.
1779
+
1780
+ Returns
1781
+ -------
1782
+ tuple[NDArray[np.int32], NDArray[np.int64]]
1783
+ Tuple of (edges, refs).
1784
+
1785
+ """
1786
+
1787
+ def set_vertex(
1788
+ self,
1789
+ x: float,
1790
+ y: float,
1791
+ z: float,
1792
+ ref: int,
1793
+ idx: int,
1794
+ ) -> None:
1795
+ """Set a single vertex.
1796
+
1797
+ Parameters
1798
+ ----------
1799
+ x, y, z : float
1800
+ Vertex coordinates.
1801
+ ref : int
1802
+ Reference marker.
1803
+ idx : int
1804
+ Vertex index (0-based).
1805
+
1806
+ """
1807
+
1808
+ def set_triangle(
1809
+ self,
1810
+ v0: int,
1811
+ v1: int,
1812
+ v2: int,
1813
+ ref: int,
1814
+ idx: int,
1815
+ ) -> None:
1816
+ """Set a single triangle.
1817
+
1818
+ Parameters
1819
+ ----------
1820
+ v0, v1, v2 : int
1821
+ Vertex indices (0-based).
1822
+ ref : int
1823
+ Reference marker.
1824
+ idx : int
1825
+ Triangle index (0-based).
1826
+
1827
+ """
1828
+
1829
+ def set_edge(self, v0: int, v1: int, ref: int, idx: int) -> None:
1830
+ """Set a single edge.
1831
+
1832
+ Parameters
1833
+ ----------
1834
+ v0, v1 : int
1835
+ Vertex indices (0-based).
1836
+ ref : int
1837
+ Reference marker.
1838
+ idx : int
1839
+ Edge index (0-based).
1840
+
1841
+ """
1842
+
1843
+ def get_vertex(self, idx: int) -> tuple[float, float, float, int]:
1844
+ """Get a single vertex.
1845
+
1846
+ Parameters
1847
+ ----------
1848
+ idx : int
1849
+ Vertex index (0-based).
1850
+
1851
+ Returns
1852
+ -------
1853
+ tuple[float, float, float, int]
1854
+ Tuple of (x, y, z, ref).
1855
+
1856
+ """
1857
+
1858
+ def get_triangle(self, idx: int) -> tuple[int, int, int, int]:
1859
+ """Get a single triangle.
1860
+
1861
+ Parameters
1862
+ ----------
1863
+ idx : int
1864
+ Triangle index (0-based).
1865
+
1866
+ Returns
1867
+ -------
1868
+ tuple[int, int, int, int]
1869
+ Tuple of (v0, v1, v2, ref).
1870
+
1871
+ """
1872
+
1873
+ def get_edge(self, idx: int) -> tuple[int, int, int]:
1874
+ """Get a single edge.
1875
+
1876
+ Parameters
1877
+ ----------
1878
+ idx : int
1879
+ Edge index (0-based).
1880
+
1881
+ Returns
1882
+ -------
1883
+ tuple[int, int, int]
1884
+ Tuple of (v0, v1, ref).
1885
+
1886
+ """
1887
+
1888
+ def set_corners(self, vertex_indices: NDArray[np.int32]) -> None:
1889
+ """Mark vertices as corners (preserved during remeshing).
1890
+
1891
+ Parameters
1892
+ ----------
1893
+ vertex_indices : NDArray[np.int32]
1894
+ Indices of corner vertices (0-based).
1895
+
1896
+ """
1897
+
1898
+ def set_required_vertices(self, vertex_indices: NDArray[np.int32]) -> None:
1899
+ """Mark vertices as required (cannot be removed).
1900
+
1901
+ Parameters
1902
+ ----------
1903
+ vertex_indices : NDArray[np.int32]
1904
+ Indices of required vertices (0-based).
1905
+
1906
+ """
1907
+
1908
+ def set_ridge_edges(self, edge_indices: NDArray[np.int32]) -> None:
1909
+ """Mark edges as ridges (sharp features preserved).
1910
+
1911
+ Parameters
1912
+ ----------
1913
+ edge_indices : NDArray[np.int32]
1914
+ Indices of ridge edges (0-based).
1915
+
1916
+ """
1917
+
1918
+ def get_adjacent_elements(self, idx: int) -> NDArray[np.int32]:
1919
+ """Get indices of triangles sharing edges with element idx.
1920
+
1921
+ Parameters
1922
+ ----------
1923
+ idx : int
1924
+ Element index (0-based).
1925
+
1926
+ Returns
1927
+ -------
1928
+ NDArray[np.int32]
1929
+ Array of 3 indices (-1 indicates boundary).
1930
+
1931
+ """
1932
+
1933
+ def get_vertex_neighbors(self, idx: int) -> NDArray[np.int32]:
1934
+ """Get indices of vertices connected to vertex idx by an edge.
1935
+
1936
+ Parameters
1937
+ ----------
1938
+ idx : int
1939
+ Vertex index (0-based).
1940
+
1941
+ Returns
1942
+ -------
1943
+ NDArray[np.int32]
1944
+ Array of neighbor vertex indices.
1945
+
1946
+ """
1947
+
1948
+ def get_element_quality(self, idx: int) -> float:
1949
+ """Get quality metric for a triangle.
1950
+
1951
+ Parameters
1952
+ ----------
1953
+ idx : int
1954
+ Triangle index (0-based).
1955
+
1956
+ Returns
1957
+ -------
1958
+ float
1959
+ Quality metric (0-1, higher is better).
1960
+
1961
+ """
1962
+
1963
+ def get_element_qualities(self) -> NDArray[np.float64]:
1964
+ """Get quality metrics for all triangles.
1965
+
1966
+ Returns
1967
+ -------
1968
+ NDArray[np.float64]
1969
+ Quality metrics for all elements.
1970
+
1971
+ """
1972
+
1973
+ def set_field(self, key: str, value: NDArray[np.float64]) -> None:
1974
+ """Set a solution field on vertices.
1975
+
1976
+ Parameters
1977
+ ----------
1978
+ key : str
1979
+ Field name: "metric", "levelset", or "tensor".
1980
+ value : NDArray[np.float64]
1981
+ Field values (one row per vertex).
1982
+
1983
+ """
1984
+
1985
+ def get_field(self, key: str) -> NDArray[np.float64]:
1986
+ """Get a solution field from vertices.
1987
+
1988
+ Parameters
1989
+ ----------
1990
+ key : str
1991
+ Field name.
1992
+
1993
+ Returns
1994
+ -------
1995
+ NDArray[np.float64]
1996
+ Field values (one row per vertex).
1997
+
1998
+ """
1999
+
2000
+ def __setitem__(self, key: str, value: NDArray[np.float64]) -> None:
2001
+ """Set a solution field using dictionary syntax."""
2002
+
2003
+ def __getitem__(self, key: str) -> NDArray[np.float64]:
2004
+ """Get a solution field using dictionary syntax."""
2005
+
2006
+ def save(self, filename: str | Path) -> None:
2007
+ """Save mesh to file.
2008
+
2009
+ Parameters
2010
+ ----------
2011
+ filename : str | Path
2012
+ Output file path. Format determined by extension.
2013
+
2014
+ """
2015
+
2016
+ def remesh(
2017
+ self,
2018
+ *,
2019
+ hmin: float | None = None,
2020
+ hmax: float | None = None,
2021
+ hsiz: float | None = None,
2022
+ hausd: float | None = None,
2023
+ hgrad: float | None = None,
2024
+ verbose: int | bool | None = None,
2025
+ optim: int | None = None,
2026
+ noinsert: int | None = None,
2027
+ noswap: int | None = None,
2028
+ nomove: int | None = None,
2029
+ **kwargs: float | None,
2030
+ ) -> dict[str, Any]:
2031
+ """Remesh the mesh in-place.
2032
+
2033
+ Parameters
2034
+ ----------
2035
+ hmin : float | None
2036
+ Minimum edge size.
2037
+ hmax : float | None
2038
+ Maximum edge size.
2039
+ hsiz : float | None
2040
+ Uniform target edge size.
2041
+ hausd : float | None
2042
+ Hausdorff distance for geometry approximation.
2043
+ hgrad : float | None
2044
+ Gradation parameter.
2045
+ verbose : int | bool | None
2046
+ Verbosity level. True/False converted to 1/-1.
2047
+ optim : int | None
2048
+ Optimization mode.
2049
+ noinsert : int | None
2050
+ Disable vertex insertion.
2051
+ noswap : int | None
2052
+ Disable edge swapping.
2053
+ nomove : int | None
2054
+ Disable vertex relocation.
2055
+ **kwargs : float | int | None
2056
+ Additional MMG options.
2057
+
2058
+ Returns
2059
+ -------
2060
+ dict[str, Any]
2061
+ Statistics dictionary with before/after metrics.
2062
+
2063
+ """
2064
+
2065
+ def remesh_lagrangian(
2066
+ self,
2067
+ displacement: NDArray[np.float64],
2068
+ **kwargs: float | None,
2069
+ ) -> None:
2070
+ """Not supported - raises RuntimeError.
2071
+
2072
+ Lagrangian motion is not supported for surface meshes (MmgMeshS).
2073
+
2074
+ Reason: Lagrangian motion requires solving elasticity PDEs to propagate
2075
+ boundary displacements to interior vertices. Surface meshes have no
2076
+ volumetric interior - the ELAS library only supports 2D/3D elasticity,
2077
+ not shell/membrane elasticity needed for surfaces.
2078
+
2079
+ Alternative: Use mmgpy.move_mesh() to move vertices and remesh:
2080
+ mmgpy.move_mesh(mesh, displacement, hausd=0.01)
2081
+
2082
+ Parameters
2083
+ ----------
2084
+ displacement : NDArray[np.float64]
2085
+ Not used - raises RuntimeError immediately.
2086
+ **kwargs : float | None
2087
+ Not used - raises RuntimeError immediately.
2088
+
2089
+ Raises
2090
+ ------
2091
+ RuntimeError
2092
+ Always raised - Lagrangian motion is not supported for surface meshes.
2093
+
2094
+ """
2095
+
2096
+ def remesh_levelset(
2097
+ self,
2098
+ levelset: NDArray[np.float64],
2099
+ *,
2100
+ ls: float | None = None,
2101
+ hmin: float | None = None,
2102
+ hmax: float | None = None,
2103
+ hsiz: float | None = None,
2104
+ hausd: float | None = None,
2105
+ hgrad: float | None = None,
2106
+ verbose: int | bool | None = None,
2107
+ iso: int | None = None,
2108
+ **kwargs: float | None,
2109
+ ) -> dict[str, Any]:
2110
+ """Remesh to conform to a level-set isoline.
2111
+
2112
+ Parameters
2113
+ ----------
2114
+ levelset : NDArray[np.float64]
2115
+ Level-set values, shape (n_vertices, 1).
2116
+ ls : float | None
2117
+ Isovalue to discretize (default 0.0).
2118
+ hmin : float | None
2119
+ Minimum edge size.
2120
+ hmax : float | None
2121
+ Maximum edge size.
2122
+ hsiz : float | None
2123
+ Uniform target edge size.
2124
+ hausd : float | None
2125
+ Hausdorff distance for geometry approximation.
2126
+ hgrad : float | None
2127
+ Gradation parameter.
2128
+ verbose : int | bool | None
2129
+ Verbosity level.
2130
+ iso : int | None
2131
+ Enable level-set mode (default 1).
2132
+ **kwargs : float | int | None
2133
+ Additional MMG options.
2134
+
2135
+ Returns
2136
+ -------
2137
+ dict[str, Any]
2138
+ Statistics dictionary with before/after metrics.
2139
+
2140
+ """