bluemesh2d 0.1.1.dev0__tar.gz → 0.1.2__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 (105) hide show
  1. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/.github/workflows/build-package.yml +4 -3
  2. bluemesh2d-0.1.2/MANIFEST.in +3 -0
  3. {bluemesh2d-0.1.1.dev0/bluemesh2d.egg-info → bluemesh2d-0.1.2}/PKG-INFO +1 -1
  4. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/_version.py +3 -3
  5. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2/bluemesh2d.egg-info}/PKG-INFO +1 -1
  6. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d.egg-info/SOURCES.txt +1 -10
  7. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d.egg-info/scm_file_list.json +3 -1
  8. bluemesh2d-0.1.2/bluemesh2d.egg-info/scm_version.json +8 -0
  9. bluemesh2d-0.1.1.dev0/bluemesh2d.egg-info/scm_version.json +0 -8
  10. bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/README.md +0 -227
  11. bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/__init__.py +0 -21
  12. bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/algorithm.py +0 -2146
  13. bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/deps_installer.py +0 -495
  14. bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/icon.png +0 -0
  15. bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/metadata.txt +0 -17
  16. bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/pipeline.py +0 -88
  17. bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/plugin.py +0 -103
  18. bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/provider.py +0 -23
  19. bluemesh2d-0.1.1.dev0/docs/Tuto_BlueMesh2D_Santander.pdf +0 -0
  20. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/.gitignore +0 -0
  21. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/LICENSE +0 -0
  22. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/README.md +0 -0
  23. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/aabb_tree/findball.py +0 -0
  24. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/aabb_tree/findtria.py +0 -0
  25. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/aabb_tree/maketree.py +0 -0
  26. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/aabb_tree/mapvert.py +0 -0
  27. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/aabb_tree/queryset.py +0 -0
  28. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/aabb_tree/scantree.py +0 -0
  29. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/dependencies.py +0 -0
  30. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/feedback.py +0 -0
  31. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geom_util/boundary_util.py +0 -0
  32. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geom_util/getiso.py +0 -0
  33. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geom_util/poly_util.py +0 -0
  34. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geom_util/proj_util.py +0 -0
  35. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geomesh_util/border_util.py +0 -0
  36. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geomesh_util/depth_field.py +0 -0
  37. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geomesh_util/grd_util.py +0 -0
  38. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geomesh_util/interpolation_mesh.py +0 -0
  39. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geomesh_util/merge_circumcenters.py +0 -0
  40. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geomesh_util/water_polygon.py +0 -0
  41. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/build_hfun.py +0 -0
  42. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/hfun_dispersion.py +0 -0
  43. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/lfshfn.py +0 -0
  44. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/limhfn.py +0 -0
  45. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/make_constant_hfun.py +0 -0
  46. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/make_depth_hfun.py +0 -0
  47. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/smooth_and_precomput.py +0 -0
  48. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/trihfn.py +0 -0
  49. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hjac_util/limgrad.py +0 -0
  50. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_ball/cdtbal1.py +0 -0
  51. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_ball/cdtbal2.py +0 -0
  52. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_ball/inv_2x2.py +0 -0
  53. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_ball/inv_3x3.py +0 -0
  54. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_ball/pwrbal2.py +0 -0
  55. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_ball/tribal2.py +0 -0
  56. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_cost/relhfn.py +0 -0
  57. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_cost/triang.py +0 -0
  58. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_cost/triarea.py +0 -0
  59. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_cost/trideg.py +0 -0
  60. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_cost/triscr.py +0 -0
  61. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_file/bnd_util.py +0 -0
  62. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_file/loadmsh.py +0 -0
  63. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_file/ugrid.py +0 -0
  64. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/cfmtri.py +0 -0
  65. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/deltri.py +0 -0
  66. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/idxtri.py +0 -0
  67. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/isfeat.py +0 -0
  68. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/minlen.py +0 -0
  69. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/setset.py +0 -0
  70. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/tricon.py +0 -0
  71. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/tridiv.py +0 -0
  72. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/meshgen.py +0 -0
  73. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/ortho_merge/constants.py +0 -0
  74. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/ortho_merge/geometry.py +0 -0
  75. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/ortho_merge/ortho_merge_iter.py +0 -0
  76. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/ortho_merge/orthogonalize.py +0 -0
  77. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/pipeline.py +0 -0
  78. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/poly_data/airfoil.msh +0 -0
  79. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/poly_data/channel.msh +0 -0
  80. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/poly_data/islands.msh +0 -0
  81. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/poly_data/lake.msh +0 -0
  82. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/poly_data/river.msh +0 -0
  83. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/poly_test/inpoly.py +0 -0
  84. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/poly_test/inpoly_mat.py +0 -0
  85. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/refine.py +0 -0
  86. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/smood.py +0 -0
  87. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/smooth.py +0 -0
  88. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/tricost.py +0 -0
  89. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/tridemo.py +0 -0
  90. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/triread.py +0 -0
  91. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d.egg-info/dependency_links.txt +0 -0
  92. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d.egg-info/requires.txt +0 -0
  93. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d.egg-info/top_level.txt +0 -0
  94. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/pyproject.toml +0 -0
  95. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/setup.cfg +0 -0
  96. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/README.md +0 -0
  97. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/__init__.py +0 -0
  98. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/_cases.py +0 -0
  99. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/conftest.py +0 -0
  100. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/reference/demo0_basic.npz +0 -0
  101. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/reference/demo0_hfun.npz +0 -0
  102. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/reference/demo6_internal.npz +0 -0
  103. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/reference/smood_square.npz +0 -0
  104. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/regenerate_references.py +0 -0
  105. {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/test_meshing.py +0 -0
@@ -26,9 +26,10 @@ jobs:
26
26
  run: pip install build
27
27
 
28
28
  - name: Build Python Package
29
- run: |
30
- rm -rf assets
31
- python -m build
29
+ # NB: never modify the worktree here -- setuptools-scm treats a dirty
30
+ # tree as "not exactly at the tag" and emits a .devN version instead.
31
+ # assets/ is kept out of the sdist by MANIFEST.in.
32
+ run: python -m build
32
33
 
33
34
  - name: Publish to PyPI
34
35
  uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,3 @@
1
+ prune assets
2
+ prune docs
3
+ prune bluemesh2d_qgis
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bluemesh2d
3
- Version: 0.1.1.dev0
3
+ Version: 0.1.2
4
4
  Summary: BlueMesh2D is a Python-based unstructured mesh-generator for two-dimensional polygonal geometries, providing a range of relatively simple, yet effective two-dimensional meshing algorithms.
5
5
  Author-email: Geomatics and Ocean Engineering Group <faugeree@unican.es>
6
6
  License-Expression: GPL-3.0-only
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.1.1.dev0'
22
- __version_tuple__ = version_tuple = (0, 1, 1, 'dev0')
21
+ __version__ = version = '0.1.2'
22
+ __version_tuple__ = version_tuple = (0, 1, 2)
23
23
 
24
- __commit_id__ = commit_id = 'gaa72c9ba7'
24
+ __commit_id__ = commit_id = 'g23470bb1a'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bluemesh2d
3
- Version: 0.1.1.dev0
3
+ Version: 0.1.2
4
4
  Summary: BlueMesh2D is a Python-based unstructured mesh-generator for two-dimensional polygonal geometries, providing a range of relatively simple, yet effective two-dimensional meshing algorithms.
5
5
  Author-email: Geomatics and Ocean Engineering Group <faugeree@unican.es>
6
6
  License-Expression: GPL-3.0-only
@@ -1,5 +1,6 @@
1
1
  .gitignore
2
2
  LICENSE
3
+ MANIFEST.in
3
4
  README.md
4
5
  pyproject.toml
5
6
  .github/workflows/build-package.yml
@@ -79,16 +80,6 @@ bluemesh2d/poly_data/lake.msh
79
80
  bluemesh2d/poly_data/river.msh
80
81
  bluemesh2d/poly_test/inpoly.py
81
82
  bluemesh2d/poly_test/inpoly_mat.py
82
- bluemesh2d_qgis/README.md
83
- bluemesh2d_qgis/__init__.py
84
- bluemesh2d_qgis/algorithm.py
85
- bluemesh2d_qgis/deps_installer.py
86
- bluemesh2d_qgis/icon.png
87
- bluemesh2d_qgis/metadata.txt
88
- bluemesh2d_qgis/pipeline.py
89
- bluemesh2d_qgis/plugin.py
90
- bluemesh2d_qgis/provider.py
91
- docs/Tuto_BlueMesh2D_Santander.pdf
92
83
  tests/README.md
93
84
  tests/__init__.py
94
85
  tests/_cases.py
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "files": [
3
+ "MANIFEST.in",
3
4
  "pyproject.toml",
4
5
  "LICENSE",
5
6
  "README.md",
@@ -92,6 +93,7 @@
92
93
  "bluemesh2d_qgis/__init__.py",
93
94
  "bluemesh2d_qgis/provider.py",
94
95
  "bluemesh2d_qgis/icon.png",
95
- "bluemesh2d_qgis/README.md"
96
+ "bluemesh2d_qgis/README.md",
97
+ "assets/mesh_geocean.webp"
96
98
  ]
97
99
  }
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.1.2",
3
+ "distance": 0,
4
+ "node": "g23470bb1a512ed0633fed31ea9c5eff762e66267",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-07-27"
8
+ }
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "0.1.0",
3
- "distance": 0,
4
- "node": "gaa72c9ba725aaa9a33640af00b3c7e7b1252126d",
5
- "dirty": true,
6
- "branch": "HEAD",
7
- "node_date": "2026-07-27"
8
- }
@@ -1,227 +0,0 @@
1
- # BlueMesh2D — QGIS plugin
2
-
3
- A self-contained QGIS **Processing** plugin that generates an unstructured
4
- triangular mesh from a bathymetry GeoTIFF, wrapping a bundled copy of the
5
- [BlueMesh2D](https://github.com/GeoOcean/BlueMesh2D) library. The output is a
6
- UGRID NetCDF that loads directly as a QGIS **mesh layer**.
7
-
8
- ## About BlueMesh2D
9
-
10
- `BlueMesh2D` (successor of `PyMesh2D`, part of the BlueMath ecosystem) is a
11
- pure-Python unstructured mesh generator for two-dimensional polygonal
12
- geometries. It is a Python translation of
13
- [`MESH2D`](https://github.com/dengwirda/mesh2d) (Darren Engwirda's MATLAB/
14
- Octave tool) and a simplified 2D sibling of his C++
15
- [`JIGSAW`](https://github.com/dengwirda/jigsaw-matlab) mesh generator.
16
-
17
- It implements:
18
- - **Delaunay refinement** and a **Frontal-Delaunay ("delfront")** scheme for
19
- generating triangulations from a boundary (PSLG) and a user-defined
20
- mesh-size function;
21
- - **non-linear mesh optimisation** (`smooth`), plus `smood`, an
22
- orthogonalization / small-link-merging pass geared at Delft3D-FM
23
- flexible-mesh quality requirements;
24
- - mesh-spacing ("hfun") utilities: gradient limiting, depth/wavelength-based
25
- sizing, local-feature-size estimation;
26
- - geometry and bathymetry pre/post-processing: coastline extraction from
27
- raster elevation, polygon resampling, CRS-aware raster/point interpolation,
28
- boundary classification (open/land), and export to ADCIRC `.grd` /
29
- Delft3D-FM UGRID NetCDF.
30
-
31
- The algorithms are "probably-good": they guarantee termination, geometric and
32
- topological correctness, and worst-case element-quality bounds, while
33
- supporting user-defined mesh-size functions and multi-part domains. See the
34
- [BlueMesh2D repository](https://github.com/GeoOcean/BlueMesh2D) for the full
35
- library, its demos (`python -m bluemesh2d.tridemo <n>`), and references.
36
-
37
- This plugin exposes the raster-to-mesh subset of that library — coastline
38
- extraction, sizing, refinement/smoothing, and export — as QGIS Processing
39
- algorithms, so the workflow can run without Python scripting and its
40
- intermediate results (water polygon, size raster, boundary, mesh) become
41
- ordinary QGIS layers.
42
-
43
- ## What it does
44
-
45
- ```
46
- bathymetry.tif
47
- → extract coastline + domain (depth threshold)
48
- → depth-based element size h = clip(a·d² + b·d, hmin, hmax)
49
- (+ optional finer 'detail' region)
50
- → gradient-limit the size field (smooth, Lipschitz)
51
- → refine (delaunay | delfront) → smooth [→ smood orthogonalization]
52
- → sample bathymetry onto nodes
53
- → write UGRID NetCDF → load as a QgsMeshLayer
54
- ```
55
-
56
- ## The algorithms (Processing Toolbox ▸ BlueMesh2D)
57
-
58
- The pipeline is available **split into four stages** — each result lands in an
59
- ordinary (temporary or saved) QGIS layer you can inspect before the next step:
60
-
61
- | algorithm | inputs | outputs |
62
- |---|---|---|
63
- | **1 – Extract water polygon** | bathy raster; coastline level; optional **deep level** (keeps the band `deep < z ≤ coast`, e.g. water shallower than 300 m); optional **extent polygon** (clips the raster *before* extraction — much faster; buffer then ignored); buffer factor (default −0.05) | water polygon layer |
64
- | **2 – Build element-size raster (hfun)** *(folder)* | one algorithm **per sizing method** (pick the algorithm, see only its parameters): **2a** depth polynomial `a·d²+b·d`; **2b** wavelength `L(T,d)/N` (Hunt 1979, `hfun_wavenumhunt`); **2c** custom Python (`d`,`x`,`y`,`np`). All share: optional **Water polygon (stage 1)** to limit computation to that area + buffer (much faster than the whole raster), detail polygons, min/max/detail size, gradient and **buffer** (m, −1 = automatic) | GeoTIFF, pixel = element size (m) |
65
- | **3 – Resample boundary to element size** | water polygon (1), hfun raster (2) | boundary **edges** line layer, styled with visible vertex markers (editable) |
66
- | **4 – Generate mesh from boundary** | **edges layer (3) — editable: move/delete/add segments first**, hfun raster (2), bathy raster; kind = delaunay/delfront; smooth; optional **smood** (+ *merge small links*, only if triangle-only smood can't remove the last small flow links) | UGRID NetCDF → mesh layer |
67
- | **5 – Generate boundary conditions** | mesh layer (4); depth threshold (default 20 m) | one **line layer** with a `btype` attribute — **open** / **closed** / **island** — styled by type with visible vertex dots, **editable** (move vertices, or change `btype` to reclassify a segment) |
68
- | **6 – Export** *(folder)* — **6a** plain UGRID, **6b** UGRID + open BC, **6c** ADCIRC `.grd` | **6a** (default): mesh layer (4) only → `.nc`, no boundary files, no boundary layer needed. **6b**: mesh (4) **+ boundary conditions (5, required)** → `.nc` and, from the `open` features, `Boundary01.pli` / `Riemann.bc` / `FlowFM_bnd.ext`. **6c**: mesh (4) + boundary conditions (5, required) → `.grd` with open/land loops (`open`→open, `closed`+`island`→land), snapping each boundary vertex back to the nearest mesh node so stage-5 edits are honoured | `.nc` / `.nc` + Delft3D-FM BC / `.grd` |
69
-
70
- Stage 4 rebuilds the PSLG from the (possibly edited) boundary lines, so you can
71
- reshape the domain before meshing; likewise stage 6 rebuilds the boundary
72
- classification from the (possibly edited) stage-5 lines, so you can hand-correct
73
- which segments are open / closed / island before exporting. The stages also
74
- chain in the **Graphical Modeler**.
75
-
76
- Every step is its own numbered folder under **BlueMesh2D** (`1 - Extract water
77
- polygon`, `2 - Build element-size raster (hfun)` with 2a/2b/2c inside, `3 -
78
- Resample boundary...`, ..., `6 - Export` with 6a/6b/6c inside).
79
- QGIS's Processing toolbox sorts grouped and ungrouped algorithms in two
80
- separate buckets rather than one merged alphabetical list, so giving every
81
- step its own group is what keeps them in numeric order 1→6 instead of the
82
- folders (2, 6) drifting away from the single algorithms.
83
-
84
- **CRS handling**: vector layers are always delivered in the input tif's CRS.
85
- If the tif is *geographic* (e.g. EPSG:4326), a local metric UTM CRS is built
86
- internally (and embedded in the hfun raster). If the tif is already
87
- *projected* (e.g. UTM), the whole pipeline runs natively in that CRS — no
88
- reprojection at all — and the output NetCDF carries metre units with a
89
- `projected_coordinate_system` grid mapping.
90
-
91
- ## Install
92
-
93
- 1. Copy this whole `bluemesh2d_qgis/` folder into your QGIS plugins directory:
94
- - **Linux**: `~/.local/share/QGIS/QGIS3/profiles/default/python/plugins/`
95
- - **Windows**: `%APPDATA%\QGIS\QGIS3\profiles\default\python\plugins\`
96
- - **macOS**: `~/Library/Application Support/QGIS/QGIS3/profiles/default/python/plugins/`
97
- 2. Restart QGIS → **Plugins ▸ Manage and Install Plugins ▸ Installed** → enable
98
- **BlueMesh2D**.
99
- 3. The algorithms appear in the **Processing Toolbox** under
100
- *BlueMesh2D ▸ 1 - Extract water polygon* (and the following stages).
101
-
102
- ### Python dependencies (important)
103
-
104
- **Automatic (recommended):** on first load the plugin checks QGIS's Python
105
- and, if packages are missing, opens a dialog listing them with an **Install
106
- now** button. pip runs inside QGIS's own interpreter — the right one on every
107
- platform — with `--user`. On Debian/Ubuntu system Python (PEP 668,
108
- "externally managed"), packages are installed into a small plugin-managed
109
- virtual environment (`.../profiles/<profile>/python/bluemesh2d_deps`,
110
- created with `--system-site-packages`) that the plugin adds to `sys.path`
111
- on load — the system Python is never modified and
112
- `--break-system-packages` is not needed. If that Python lacks pip entirely
113
- (no `python3-pip`), pip is bootstrapped into the venv automatically with
114
- the official `get-pip.py`. On conda-based QGIS the dialog
115
- shows the `conda install` command instead of running pip. Optional packages
116
- appear as opt-in checkboxes.
117
- Restart QGIS after installing. The same dialog can be reopened anytime from
118
- **Plugins ▸ BlueMesh2D ▸ Check / install dependencies**. The commands below
119
- are the manual fallback if the dialog's pip fails.
120
-
121
- Required in **QGIS's own Python** (all commonly present already):
122
-
123
- ```
124
- numpy scipy shapely pyproj matplotlib contourpy rasterio netCDF4
125
- ```
126
-
127
- Optional:
128
-
129
- - **`triangle`** — Shewchuk's Triangle, for fast *constrained* Delaunay
130
- triangulation. Without it the plugin automatically falls back to a
131
- pure-`scipy` *conforming* Delaunay (same mesh character, somewhat slower).
132
- - **`xarray`** — required only by the **"Apply smood"** option (stage 4 /
133
- all-in-one). `bluemesh2d.smood` always builds an in-memory
134
- `xarray.Dataset` internally, regardless of the *merge small links*
135
- sub-option. It is **not** needed for anything else — in particular every
136
- UGRID NetCDF export (stage 6a and the all-in-one output) is written
137
- directly with `netCDF4`. If it's missing, the algorithm now fails
138
- immediately with a clear message instead of partway through refinement;
139
- either install `xarray` or leave "Apply smood" unchecked.
140
-
141
- If something is missing, the algorithm names it up front. To install into the
142
- interpreter QGIS uses:
143
-
144
- - **Windows** — open the *OSGeo4W Shell* and run:
145
- ```
146
- python -m pip install rasterio netCDF4 xarray # + triangle (optional)
147
- ```
148
- - **Linux** — install into the Python QGIS runs on (Debian/Ubuntu system
149
- Python needs `--break-system-packages` with `--user`):
150
- ```
151
- python3 -m pip install --user rasterio netCDF4 xarray # + triangle (optional)
152
- ```
153
- - **macOS** — the official QGIS.app bundles its **own** Python, so a plain
154
- `python3 -m pip install` (Homebrew/system Python) installs into the wrong
155
- interpreter. The reliable way — it works on every bundle layout — is to run
156
- pip from inside the **QGIS Python console** (Plugins > Python Console):
157
- ```python
158
- import pip
159
- pip.main(["install", "--user", "rasterio", "netCDF4", "xarray", "contourpy"]) # + "triangle" (optional)
160
- ```
161
- then **restart QGIS**. `--user` installs into `~/Library/Python/3.x/...`,
162
- which QGIS has on its path.
163
-
164
- Notes on the Terminal route: on **recent QGIS bundles** (vcpkg-based,
165
- ~3.40+) the bundled interpreter
166
- (`/Applications/QGIS.app/Contents/MacOS/python3.12`) **cannot run
167
- standalone** — it aborts with `ModuleNotFoundError: No module named
168
- 'encodings'` because its library prefix is baked to the build machine's
169
- path — so use the Python-console method above. On **older bundles** the
170
- Terminal command was:
171
- ```
172
- /Applications/QGIS.app/Contents/MacOS/bin/python3 -m pip install rasterio netCDF4 xarray
173
- ```
174
- (Adjust the app name if yours is e.g. `QGIS-LTR.app`.) Do **not** use
175
- `subprocess` with `sys.executable` from the QGIS console on macOS: there
176
- `sys.executable` points to the QGIS application binary, not to Python.
177
-
178
- If you installed QGIS via **conda** (`conda install -c conda-forge qgis`),
179
- install the packages into that same conda environment instead:
180
- ```
181
- conda install -c conda-forge rasterio netcdf4 xarray
182
- ```
183
-
184
- If `rasterio` clashes with QGIS's bundled GDAL on your platform, run the
185
- pipeline out-of-process instead (see below).
186
-
187
- ## Layout
188
-
189
- ```
190
- bluemesh2d_qgis/
191
- ├── __init__.py classFactory (QGIS entry point)
192
- ├── metadata.txt plugin metadata (hasProcessingProvider=yes)
193
- ├── plugin.py registers the Processing provider
194
- ├── provider.py BlueMesh2DProvider
195
- ├── algorithm.py Processing algorithms
196
- ├── pipeline.py headless orchestration facade (no QGIS dependency)
197
- └── bluemesh2d/ bundled copy of the meshing library
198
- ```
199
-
200
- `pipeline.py` is the integration seam: it puts the plugin directory on
201
- `sys.path` so the bundled `bluemesh2d` imports as a top-level package, forces
202
- the non-interactive `Agg` matplotlib backend (the contour extraction needs it),
203
- routes progress/cancellation through the algorithm's
204
- `QgsProcessingFeedback`, and captures the mesher's stdout into the log.
205
-
206
- ## Usage
207
-
208
- - **Bathymetry raster** — GeoTIFF, elevation positive up (depth = −elevation).
209
- - **Detail region** *(optional)* — a polygon layer; its union is refined down to
210
- *Detail min element size*. Digitize it in QGIS or load a file; any CRS (it is
211
- reprojected to the raster CRS automatically).
212
- - **Sizing** — *Min/Max element size*, depth coefficients *a*, *b*, and
213
- *Max size gradient* (m/m; lower = smoother, wider fine-to-coarse transitions).
214
- - **Output** — choose a `.nc` path. On success the mesh is added to the project.
215
-
216
- > Element count scales as 1/h². A small *Min size* over a large *Detail region*
217
- > can produce millions of triangles and exhaust memory — keep the detail area
218
- > tight and the floor sensible.
219
-
220
- ## Notes
221
-
222
- - The bundled `bluemesh2d` is a **copy** — update it by re-syncing the upstream
223
- `bluemesh2d/` package into the plugin root (`rsync -a --exclude=__pycache__
224
- --exclude=poly_data <repo>/bluemesh2d/ bluemesh2d_qgis/bluemesh2d/`).
225
- - Currently exposes the core raster→mesh path. ADCIRC `.grd`, Delft3D-FM forcing
226
- (`.pli`/`.bc`/`.ext`) and quality reports exist in the library and can be added
227
- as further algorithms.
@@ -1,21 +0,0 @@
1
- """BlueMesh2D QGIS plugin package.
2
-
3
- QGIS calls :func:`classFactory` to instantiate the plugin.
4
- """
5
-
6
-
7
- def classFactory(iface):
8
- """Instantiate the plugin (QGIS's mandated plugin entry point).
9
-
10
- Parameters
11
- ----------
12
- iface : qgis.gui.QgisInterface
13
- QGIS application interface, passed in by QGIS.
14
-
15
- Returns
16
- -------
17
- plugin : plugin.BlueMesh2DPlugin
18
- The plugin instance.
19
- """
20
- from .plugin import BlueMesh2DPlugin
21
- return BlueMesh2DPlugin(iface)