liblaf-melon 0.2.2__tar.gz → 0.2.3__tar.gz

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 (122) hide show
  1. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/PKG-INFO +2 -2
  2. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/pyproject.toml +1 -4
  3. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/__init__.pyi +9 -1
  4. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/_version.py +2 -2
  5. liblaf_melon-0.2.3/src/liblaf/melon/barycentric/__init__.pyi +4 -0
  6. liblaf_melon-0.2.3/src/liblaf/melon/barycentric/_points.py +15 -0
  7. liblaf_melon-0.2.3/src/liblaf/melon/barycentric/_sample.py +15 -0
  8. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/__init__.pyi +5 -1
  9. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/abc/_writer.py +1 -0
  10. liblaf_melon-0.2.3/src/liblaf/melon/io/paraview/__init__.pyi +4 -0
  11. liblaf_melon-0.2.3/src/liblaf/melon/io/paraview/_pvd_writer.py +72 -0
  12. liblaf_melon-0.2.3/src/liblaf/melon/io/paraview/_series_writer.py +118 -0
  13. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/triangle/__init__.pyi +4 -0
  14. liblaf_melon-0.2.3/src/liblaf/melon/triangle/_boolean.py +16 -0
  15. liblaf_melon-0.2.3/src/liblaf/melon/triangle/_ray.py +14 -0
  16. liblaf_melon-0.2.3/src/liblaf/melon/typed/__init__.py +3 -0
  17. liblaf_melon-0.2.3/src/liblaf/melon/utils/__init__.py +3 -0
  18. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/.gitignore +0 -0
  19. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/LICENSE +0 -0
  20. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/docs/README.md +0 -0
  21. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/__init__.py +0 -0
  22. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/_version.pyi +0 -0
  23. {liblaf_melon-0.2.2/src/liblaf/melon/io → liblaf_melon-0.2.3/src/liblaf/melon/barycentric}/__init__.py +0 -0
  24. {liblaf_melon-0.2.2/src/liblaf/melon/io/abc → liblaf_melon-0.2.3/src/liblaf/melon/io}/__init__.py +0 -0
  25. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/_save.py +0 -0
  26. {liblaf_melon-0.2.2/src/liblaf/melon/io/pyvista → liblaf_melon-0.2.3/src/liblaf/melon/io/abc}/__init__.py +0 -0
  27. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/abc/__init__.pyi +0 -0
  28. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/abc/_converter.py +0 -0
  29. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/abc/_reader.py +0 -0
  30. {liblaf_melon-0.2.2/src/liblaf/melon/io/pyvista/point_set → liblaf_melon-0.2.3/src/liblaf/melon/io/paraview}/__init__.py +0 -0
  31. {liblaf_melon-0.2.2/src/liblaf/melon/io/pyvista/point_set/convert → liblaf_melon-0.2.3/src/liblaf/melon/io/pyvista}/__init__.py +0 -0
  32. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/__init__.pyi +0 -0
  33. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/_convert.py +0 -0
  34. {liblaf_melon-0.2.2/src/liblaf/melon/io/pyvista/poly_data → liblaf_melon-0.2.3/src/liblaf/melon/io/pyvista/point_set}/__init__.py +0 -0
  35. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/point_set/__init__.pyi +0 -0
  36. {liblaf_melon-0.2.2/src/liblaf/melon/io/pyvista/poly_data → liblaf_melon-0.2.3/src/liblaf/melon/io/pyvista/point_set}/convert/__init__.py +0 -0
  37. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/point_set/convert/__init__.pyi +0 -0
  38. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/point_set/convert/_array.py +0 -0
  39. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/point_set/convert/_convert.py +0 -0
  40. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/point_set/convert/_poly_data.py +0 -0
  41. {liblaf_melon-0.2.2/src/liblaf/melon/io/pyvista/poly_data/reader → liblaf_melon-0.2.3/src/liblaf/melon/io/pyvista/poly_data}/__init__.py +0 -0
  42. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/poly_data/__init__.pyi +0 -0
  43. {liblaf_melon-0.2.2/src/liblaf/melon/io/pyvista/poly_data/writer → liblaf_melon-0.2.3/src/liblaf/melon/io/pyvista/poly_data/convert}/__init__.py +0 -0
  44. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/poly_data/convert/__init__.pyi +0 -0
  45. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/poly_data/convert/_convert.py +0 -0
  46. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/poly_data/convert/_mapping.py +0 -0
  47. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/poly_data/convert/_wrap.py +0 -0
  48. {liblaf_melon-0.2.2/src/liblaf/melon/io/pyvista/unstructured_grid → liblaf_melon-0.2.3/src/liblaf/melon/io/pyvista/poly_data/reader}/__init__.py +0 -0
  49. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/poly_data/reader/__init__.pyi +0 -0
  50. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/poly_data/reader/_load.py +0 -0
  51. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/poly_data/reader/_obj.py +0 -0
  52. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/poly_data/reader/_pyvista.py +0 -0
  53. {liblaf_melon-0.2.2/src/liblaf/melon/io/pyvista/unstructured_grid/convert → liblaf_melon-0.2.3/src/liblaf/melon/io/pyvista/poly_data/writer}/__init__.py +0 -0
  54. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/poly_data/writer/__init__.pyi +0 -0
  55. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/poly_data/writer/_pyvista.py +0 -0
  56. {liblaf_melon-0.2.2/src/liblaf/melon/io/pyvista/unstructured_grid/reader → liblaf_melon-0.2.3/src/liblaf/melon/io/pyvista/unstructured_grid}/__init__.py +0 -0
  57. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/unstructured_grid/__init__.pyi +0 -0
  58. {liblaf_melon-0.2.2/src/liblaf/melon/io/pyvista/unstructured_grid/writer → liblaf_melon-0.2.3/src/liblaf/melon/io/pyvista/unstructured_grid/convert}/__init__.py +0 -0
  59. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/unstructured_grid/convert/__init__.pyi +0 -0
  60. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/unstructured_grid/convert/_convert.py +0 -0
  61. {liblaf_melon-0.2.2/src/liblaf/melon/io/trimesh → liblaf_melon-0.2.3/src/liblaf/melon/io/pyvista/unstructured_grid/reader}/__init__.py +0 -0
  62. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/unstructured_grid/reader/__init__.pyi +0 -0
  63. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/unstructured_grid/reader/_pyvista.py +0 -0
  64. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/unstructured_grid/reader/_reader.py +0 -0
  65. {liblaf_melon-0.2.2/src/liblaf/melon/io/trimesh/convert → liblaf_melon-0.2.3/src/liblaf/melon/io/pyvista/unstructured_grid/writer}/__init__.py +0 -0
  66. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/unstructured_grid/writer/__init__.pyi +0 -0
  67. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/pyvista/unstructured_grid/writer/_pyvista.py +0 -0
  68. {liblaf_melon-0.2.2/src/liblaf/melon/io/trimesh/reader → liblaf_melon-0.2.3/src/liblaf/melon/io/trimesh}/__init__.py +0 -0
  69. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/trimesh/__init__.pyi +0 -0
  70. {liblaf_melon-0.2.2/src/liblaf/melon/io/trimesh/writer → liblaf_melon-0.2.3/src/liblaf/melon/io/trimesh/convert}/__init__.py +0 -0
  71. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/trimesh/convert/__init__.pyi +0 -0
  72. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/trimesh/convert/_convert.py +0 -0
  73. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/trimesh/convert/_poly_data.py +0 -0
  74. {liblaf_melon-0.2.2/src/liblaf/melon/io/wrap → liblaf_melon-0.2.3/src/liblaf/melon/io/trimesh/reader}/__init__.py +0 -0
  75. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/trimesh/reader/__init__.pyi +0 -0
  76. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/trimesh/reader/_reader.py +0 -0
  77. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/trimesh/reader/_trimesh.py +0 -0
  78. {liblaf_melon-0.2.2/src/liblaf/melon/io/wrap/landmarks → liblaf_melon-0.2.3/src/liblaf/melon/io/trimesh/writer}/__init__.py +0 -0
  79. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/trimesh/writer/__init__.pyi +0 -0
  80. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/trimesh/writer/_trimesh.py +0 -0
  81. {liblaf_melon-0.2.2/src/liblaf/melon/io/wrap/polygons → liblaf_melon-0.2.3/src/liblaf/melon/io/wrap}/__init__.py +0 -0
  82. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/wrap/__init__.pyi +0 -0
  83. {liblaf_melon-0.2.2/src/liblaf/melon/mesh → liblaf_melon-0.2.3/src/liblaf/melon/io/wrap/landmarks}/__init__.py +0 -0
  84. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/wrap/landmarks/__init__.pyi +0 -0
  85. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/wrap/landmarks/_reader.py +0 -0
  86. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/wrap/landmarks/_utils.py +0 -0
  87. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/wrap/landmarks/_writer.py +0 -0
  88. {liblaf_melon-0.2.2/src/liblaf/melon/plugin → liblaf_melon-0.2.3/src/liblaf/melon/io/wrap/polygons}/__init__.py +0 -0
  89. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/wrap/polygons/__init__.pyi +0 -0
  90. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/wrap/polygons/_reader.py +0 -0
  91. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/wrap/polygons/_utils.py +0 -0
  92. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/io/wrap/polygons/_writer.py +0 -0
  93. {liblaf_melon-0.2.2/src/liblaf/melon/plugin/wrap → liblaf_melon-0.2.3/src/liblaf/melon/mesh}/__init__.py +0 -0
  94. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/mesh/__init__.pyi +0 -0
  95. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/mesh/_graph.py +0 -0
  96. {liblaf_melon-0.2.2/src/liblaf/melon/proximity → liblaf_melon-0.2.3/src/liblaf/melon/plugin}/__init__.py +0 -0
  97. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/plugin/__init__.pyi +0 -0
  98. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/plugin/_mesh_fix.py +0 -0
  99. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/plugin/_tetwild.py +0 -0
  100. {liblaf_melon-0.2.2/src/liblaf/melon/tetra → liblaf_melon-0.2.3/src/liblaf/melon/plugin/wrap}/__init__.py +0 -0
  101. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/plugin/wrap/__init__.pyi +0 -0
  102. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/plugin/wrap/_annotate_landmarks.py +0 -0
  103. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/plugin/wrap/_fast_wrapping.py +0 -0
  104. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/plugin/wrap/annotate-landmarks.wrap +0 -0
  105. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/plugin/wrap/fast-wrapping.wrap +0 -0
  106. {liblaf_melon-0.2.2/src/liblaf/melon/triangle → liblaf_melon-0.2.3/src/liblaf/melon/proximity}/__init__.py +0 -0
  107. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/proximity/__init__.pyi +0 -0
  108. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/proximity/_abc.py +0 -0
  109. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/proximity/_nearest.py +0 -0
  110. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/proximity/_nearest_point.py +0 -0
  111. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/py.typed +0 -0
  112. {liblaf_melon-0.2.2/src/liblaf/melon/typed → liblaf_melon-0.2.3/src/liblaf/melon/tetra}/__init__.py +0 -0
  113. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/tetra/__init__.pyi +0 -0
  114. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/tetra/_flip.py +0 -0
  115. {liblaf_melon-0.2.2/src/liblaf/melon/utils → liblaf_melon-0.2.3/src/liblaf/melon/triangle}/__init__.py +0 -0
  116. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/triangle/_compute_edge_length.py +0 -0
  117. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/triangle/_extract.py +0 -0
  118. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/triangle/_selection.py +0 -0
  119. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/typed/__init__.pyi +0 -0
  120. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/typed/_misc.py +0 -0
  121. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/utils/__init__.pyi +0 -0
  122. {liblaf_melon-0.2.2 → liblaf_melon-0.2.3}/src/liblaf/melon/utils/_typing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: liblaf-melon
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Add your description here
5
5
  Project-URL: Changelog, https://github.com/liblaf/melon/blob/main/CHANGELOG.md
6
6
  Project-URL: Documentation, https://liblaf.github.io/melon/
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python
20
20
  Classifier: Programming Language :: Python :: 3
21
21
  Classifier: Programming Language :: Python :: 3.12
22
22
  Classifier: Typing :: Typed
23
- Requires-Python: >=3.12
23
+ Requires-Python: <3.13,>=3.12
24
24
  Requires-Dist: attrs<26,>=25.3.0
25
25
  Requires-Dist: einops<0.9,>=0.8.1
26
26
  Requires-Dist: fast-simplification<0.2,>=0.1.11
@@ -84,7 +84,7 @@ keywords = []
84
84
  license = "MIT"
85
85
  name = "liblaf-melon"
86
86
  readme = "docs/README.md"
87
- requires-python = ">=3.12"
87
+ requires-python = ">=3.12,<3.13"
88
88
 
89
89
  [project.scripts]
90
90
  melon = "liblaf.melon.cli:main"
@@ -116,9 +116,6 @@ packages = ["src/liblaf/"]
116
116
  [tool.hatch.version]
117
117
  source = "vcs"
118
118
 
119
- [tool.pixi.dependencies]
120
- python = ">=3.13,<3.14"
121
-
122
119
  [tool.pixi.environments]
123
120
  default = { features = ["build", "dev", "docs", "test"] }
124
121
 
@@ -1,6 +1,9 @@
1
- from . import io, mesh, plugin, proximity, triangle, typed, utils
1
+ from . import barycentric, io, mesh, plugin, proximity, triangle, typed, utils
2
2
  from ._version import __version__, __version_tuple__, version, version_tuple
3
+ from .barycentric import barycentric_to_points, sample_barycentric_coords
3
4
  from .io import (
5
+ PVDWriter,
6
+ SeriesWriter,
4
7
  as_poly_data,
5
8
  as_trimesh,
6
9
  as_unstructured_grid,
@@ -29,12 +32,16 @@ __all__ = [
29
32
  "NearestPointPrepared",
30
33
  "NearestPrepared",
31
34
  "NearestResult",
35
+ "PVDWriter",
36
+ "SeriesWriter",
32
37
  "__version__",
33
38
  "__version_tuple__",
34
39
  "annotate_landmarks",
35
40
  "as_poly_data",
36
41
  "as_trimesh",
37
42
  "as_unstructured_grid",
43
+ "barycentric",
44
+ "barycentric_to_points",
38
45
  "fast_wrapping",
39
46
  "io",
40
47
  "load_landmarks",
@@ -47,6 +54,7 @@ __all__ = [
47
54
  "nearest",
48
55
  "plugin",
49
56
  "proximity",
57
+ "sample_barycentric_coords",
50
58
  "save",
51
59
  "save_landmarks",
52
60
  "save_polygons",
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.2.2'
21
- __version_tuple__ = version_tuple = (0, 2, 2)
20
+ __version__ = version = '0.2.3'
21
+ __version_tuple__ = version_tuple = (0, 2, 3)
@@ -0,0 +1,4 @@
1
+ from ._points import barycentric_to_points
2
+ from ._sample import sample_barycentric_coords
3
+
4
+ __all__ = ["barycentric_to_points", "sample_barycentric_coords"]
@@ -0,0 +1,15 @@
1
+ import einops
2
+ import numpy as np
3
+ from jaxtyping import Float
4
+ from numpy.typing import ArrayLike
5
+
6
+
7
+ def barycentric_to_points(
8
+ cells: Float[ArrayLike, "N B D"], barycentric: Float[ArrayLike, "N B"]
9
+ ) -> Float[np.ndarray, "N D"]:
10
+ cells: Float[np.ndarray, "N B D"] = np.asarray(cells)
11
+ barycentric: Float[np.ndarray, "N B"] = np.asarray(barycentric)
12
+ points: Float[np.ndarray, "N D"] = einops.einsum(
13
+ barycentric, cells, "N B, N B D -> N D"
14
+ )
15
+ return points
@@ -0,0 +1,15 @@
1
+ import numpy as np
2
+ from jaxtyping import Float
3
+
4
+
5
+ def sample_barycentric_coords(
6
+ shape: tuple[int, int], generator: np.random.Generator | None = None
7
+ ) -> Float[np.ndarray, "N D"]:
8
+ if generator is None:
9
+ generator = np.random.default_rng()
10
+ n_samples: int = shape[0]
11
+ dim: int = shape[1]
12
+ coords: Float[np.ndarray, "N D-1"] = generator.uniform(0, 1, (n_samples, dim - 1))
13
+ coords: Float[np.ndarray, "N D-1"] = np.sort(coords, axis=1)
14
+ coords: Float[np.ndarray, "N D"] = np.diff(coords, axis=1, prepend=0, append=1)
15
+ return coords
@@ -1,5 +1,6 @@
1
- from . import abc, pyvista, trimesh
1
+ from . import abc, paraview, pyvista, trimesh
2
2
  from ._save import save
3
+ from .paraview import PVDWriter, SeriesWriter
3
4
  from .pyvista import (
4
5
  as_mesh,
5
6
  as_point_set,
@@ -19,6 +20,8 @@ from .wrap import (
19
20
  )
20
21
 
21
22
  __all__ = [
23
+ "PVDWriter",
24
+ "SeriesWriter",
22
25
  "abc",
23
26
  "as_mesh",
24
27
  "as_point_set",
@@ -32,6 +35,7 @@ __all__ = [
32
35
  "load_polygons",
33
36
  "load_trimesh",
34
37
  "load_unstructured_grid",
38
+ "paraview",
35
39
  "pyvista",
36
40
  "save",
37
41
  "save_landmarks",
@@ -52,6 +52,7 @@ class WriterDispatcher:
52
52
  def save(self, path: PathLike, data: Any, /, **kwargs) -> None:
53
53
  for writer in self.writers:
54
54
  if writer.match_data(data) and writer.match_path(path):
55
+ Path(path).parent.mkdir(parents=True, exist_ok=True)
55
56
  writer.save(path, data, **kwargs)
56
57
  logger.debug('Saved {} to "{}".', type(data), path)
57
58
  return
@@ -0,0 +1,4 @@
1
+ from ._pvd_writer import PVDWriter
2
+ from ._series_writer import SeriesWriter
3
+
4
+ __all__ = ["PVDWriter", "SeriesWriter"]
@@ -0,0 +1,72 @@
1
+ import shutil
2
+ from pathlib import Path
3
+ from typing import Any
4
+ from xml.etree import ElementTree
5
+
6
+ import attrs
7
+
8
+ from liblaf.melon.io._save import save
9
+
10
+
11
+ @attrs.frozen(kw_only=True)
12
+ class PVDDataSet:
13
+ timestep: float
14
+ part: int
15
+ file: Path
16
+
17
+
18
+ @attrs.frozen
19
+ class PVDWriter:
20
+ """.
21
+
22
+ References:
23
+ [1]: [ParaView/Data formats - KitwarePublic](https://www.paraview.org/Wiki/ParaView/Data_formats#PVD_File_Format)
24
+ """
25
+
26
+ @property
27
+ def folder(self) -> Path:
28
+ return self.file.with_suffix("")
29
+
30
+ @property
31
+ def name(self) -> str:
32
+ return self.file.stem
33
+
34
+ clear: bool = attrs.field(default=False, kw_only=True)
35
+ datasets: list[PVDDataSet] = attrs.field(init=False, factory=list)
36
+ file: Path = attrs.field(default=Path("animation.pvd"), converter=Path)
37
+ fps: float = attrs.field(default=30.0, kw_only=True)
38
+
39
+ def __attrs_post_init__(self) -> None:
40
+ if self.clear:
41
+ shutil.rmtree(self.folder, ignore_errors=True)
42
+
43
+ def end(self) -> None:
44
+ root = ElementTree.Element(
45
+ "VTKFile", type="Collection", version="0.1", byte_order="LittleEndian"
46
+ )
47
+ collection: ElementTree.Element = ElementTree.SubElement(root, "Collection")
48
+ root_dir: Path = self.file.absolute().parent
49
+ for dataset in self.datasets:
50
+ elem: ElementTree.Element = ElementTree.SubElement(collection, "DataSet")
51
+ elem.set("timestep", str(dataset.timestep))
52
+ elem.set("part", str(dataset.part))
53
+ elem.set("file", dataset.file.absolute().relative_to(root_dir).as_posix())
54
+ tree = ElementTree.ElementTree(root)
55
+ ElementTree.indent(tree, space=" ")
56
+ self.file.parent.mkdir(parents=True, exist_ok=True)
57
+ tree.write(self.file, xml_declaration=True)
58
+
59
+ def append(
60
+ self, dataset: Any, timestep: float | None = None, *, ext: str, part: int = 0
61
+ ) -> None:
62
+ if timestep is None:
63
+ timestep = (
64
+ self.datasets[-1].timestep + (1 / self.fps) if self.datasets else 0
65
+ )
66
+ frame_id: int = len(self.datasets)
67
+ filename: str = f"{self.name}_{frame_id:06d}"
68
+ filename += ext
69
+ filepath: Path = self.folder / filename
70
+ save(filepath, dataset)
71
+ self.datasets.append(PVDDataSet(timestep=timestep, part=part, file=filepath))
72
+ self.end()
@@ -0,0 +1,118 @@
1
+ import contextlib
2
+ import os
3
+ import shutil
4
+ import types
5
+ from collections.abc import Sequence
6
+ from pathlib import Path
7
+ from typing import Any, Literal, Self, overload
8
+
9
+ import pydantic
10
+
11
+ from liblaf import grapes
12
+ from liblaf.melon.io._save import save
13
+
14
+
15
+ def snake_to_kebab(snake: str) -> str:
16
+ return snake.replace("_", "-")
17
+
18
+
19
+ class File(pydantic.BaseModel):
20
+ name: str
21
+ time: float
22
+
23
+
24
+ class Series(pydantic.BaseModel):
25
+ model_config = pydantic.ConfigDict(alias_generator=snake_to_kebab)
26
+ file_series_version: Literal["1.0"] = "1.0"
27
+ files: list[File] = []
28
+
29
+
30
+ class SeriesWriter(Sequence[File], contextlib.AbstractContextManager):
31
+ file: Path
32
+ series: Series
33
+ timestep: float
34
+
35
+ def __init__(
36
+ self,
37
+ path: str | os.PathLike[str],
38
+ /,
39
+ *,
40
+ clear: bool = False,
41
+ fps: float = 30.0,
42
+ timestep: float | None = None,
43
+ ) -> None:
44
+ self.file = grapes.as_path(path)
45
+ self.series = Series()
46
+ if timestep is not None:
47
+ self.timestep = timestep
48
+ else:
49
+ self.timestep = 1.0 / fps
50
+
51
+ if clear:
52
+ shutil.rmtree(self.folder, ignore_errors=True)
53
+
54
+ @overload
55
+ def __getitem__(self, index: int) -> File: ...
56
+ @overload
57
+ def __getitem__(self, index: slice) -> list[File]: ...
58
+ def __getitem__(self, index: int | slice) -> File | list[File]:
59
+ return self.series.files[index]
60
+
61
+ def __len__(self) -> int:
62
+ return len(self.series.files)
63
+
64
+ def __enter__(self) -> Self:
65
+ self.start()
66
+ return self
67
+
68
+ def __exit__(
69
+ self,
70
+ exc_type: type[BaseException] | None,
71
+ exc_value: BaseException | None,
72
+ traceback: types.TracebackType | None,
73
+ ) -> None:
74
+ self.end()
75
+
76
+ @property
77
+ def ext(self) -> str:
78
+ return self.file.suffixes[-2]
79
+
80
+ @property
81
+ def folder(self) -> Path:
82
+ return self.file.parent
83
+
84
+ @property
85
+ def fps(self) -> float:
86
+ return 1.0 / self.timestep
87
+
88
+ @property
89
+ def name(self) -> str:
90
+ return self.file.with_suffix("").stem
91
+
92
+ @property
93
+ def time(self) -> float:
94
+ if len(self) == 0:
95
+ return 0.0
96
+ return self.series.files[-1].time
97
+
98
+ def append(
99
+ self, data: Any, *, time: float | None = None, timestep: float | None = None
100
+ ) -> None:
101
+ filename: str = f"{self.name}_{len(self):06d}{self.ext}"
102
+ ic(filename, self.ext, self.file)
103
+ save(self.folder / filename, data)
104
+ if time is None:
105
+ if timestep is None:
106
+ timestep = self.timestep
107
+ time = self.time + timestep
108
+ self.series.files.append(File(name=filename, time=time))
109
+ self.save()
110
+
111
+ def end(self) -> None:
112
+ self.save()
113
+
114
+ def save(self) -> None:
115
+ grapes.save_json(self.file, self.series.model_dump(by_alias=True))
116
+
117
+ def start(self) -> None:
118
+ pass
@@ -1,11 +1,15 @@
1
+ from ._boolean import intersection
1
2
  from ._compute_edge_length import compute_edge_lengths
2
3
  from ._extract import extract_cells, extract_groups, extract_points
4
+ from ._ray import contains
3
5
  from ._selection import select_groups
4
6
 
5
7
  __all__ = [
6
8
  "compute_edge_lengths",
9
+ "contains",
7
10
  "extract_cells",
8
11
  "extract_groups",
9
12
  "extract_points",
13
+ "intersection",
10
14
  "select_groups",
11
15
  ]
@@ -0,0 +1,16 @@
1
+ from collections.abc import Sequence
2
+ from typing import Any, Literal
3
+
4
+ import trimesh as tm
5
+
6
+
7
+ def intersection(
8
+ meshes: Sequence[Any],
9
+ *,
10
+ engine: Literal["blender", "manifold"] | None = None,
11
+ check_volume: bool = True,
12
+ **kwargs,
13
+ ) -> tm.Trimesh:
14
+ return tm.boolean.intersection(
15
+ meshes, engine=engine, check_volume=check_volume, **kwargs
16
+ )
@@ -0,0 +1,14 @@
1
+ from typing import Any
2
+
3
+ import numpy as np
4
+ import pyvista as pv
5
+ import trimesh as tm
6
+ from jaxtyping import Bool
7
+
8
+ from liblaf.melon import io
9
+
10
+
11
+ def contains(mesh: Any, pcl: Any) -> Bool[np.ndarray, " N"]:
12
+ mesh: tm.Trimesh = io.as_trimesh(mesh)
13
+ pcl: pv.PointSet = io.as_point_set(pcl)
14
+ return mesh.contains(pcl.points)
@@ -0,0 +1,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
@@ -0,0 +1,3 @@
1
+ import lazy_loader as lazy
2
+
3
+ __getattr__, __dir__, __all__ = lazy.attach_stub(__name__, __file__)
File without changes
File without changes