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.
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/.github/workflows/build-package.yml +4 -3
- bluemesh2d-0.1.2/MANIFEST.in +3 -0
- {bluemesh2d-0.1.1.dev0/bluemesh2d.egg-info → bluemesh2d-0.1.2}/PKG-INFO +1 -1
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/_version.py +3 -3
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2/bluemesh2d.egg-info}/PKG-INFO +1 -1
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d.egg-info/SOURCES.txt +1 -10
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d.egg-info/scm_file_list.json +3 -1
- bluemesh2d-0.1.2/bluemesh2d.egg-info/scm_version.json +8 -0
- bluemesh2d-0.1.1.dev0/bluemesh2d.egg-info/scm_version.json +0 -8
- bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/README.md +0 -227
- bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/__init__.py +0 -21
- bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/algorithm.py +0 -2146
- bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/deps_installer.py +0 -495
- bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/icon.png +0 -0
- bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/metadata.txt +0 -17
- bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/pipeline.py +0 -88
- bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/plugin.py +0 -103
- bluemesh2d-0.1.1.dev0/bluemesh2d_qgis/provider.py +0 -23
- bluemesh2d-0.1.1.dev0/docs/Tuto_BlueMesh2D_Santander.pdf +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/.gitignore +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/LICENSE +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/README.md +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/aabb_tree/findball.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/aabb_tree/findtria.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/aabb_tree/maketree.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/aabb_tree/mapvert.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/aabb_tree/queryset.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/aabb_tree/scantree.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/dependencies.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/feedback.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geom_util/boundary_util.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geom_util/getiso.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geom_util/poly_util.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geom_util/proj_util.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geomesh_util/border_util.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geomesh_util/depth_field.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geomesh_util/grd_util.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geomesh_util/interpolation_mesh.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geomesh_util/merge_circumcenters.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/geomesh_util/water_polygon.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/build_hfun.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/hfun_dispersion.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/lfshfn.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/limhfn.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/make_constant_hfun.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/make_depth_hfun.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/smooth_and_precomput.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hfun_util/trihfn.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/hjac_util/limgrad.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_ball/cdtbal1.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_ball/cdtbal2.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_ball/inv_2x2.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_ball/inv_3x3.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_ball/pwrbal2.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_ball/tribal2.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_cost/relhfn.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_cost/triang.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_cost/triarea.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_cost/trideg.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_cost/triscr.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_file/bnd_util.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_file/loadmsh.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_file/ugrid.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/cfmtri.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/deltri.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/idxtri.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/isfeat.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/minlen.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/setset.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/tricon.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/mesh_util/tridiv.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/meshgen.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/ortho_merge/constants.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/ortho_merge/geometry.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/ortho_merge/ortho_merge_iter.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/ortho_merge/orthogonalize.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/pipeline.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/poly_data/airfoil.msh +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/poly_data/channel.msh +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/poly_data/islands.msh +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/poly_data/lake.msh +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/poly_data/river.msh +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/poly_test/inpoly.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/poly_test/inpoly_mat.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/refine.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/smood.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/smooth.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/tricost.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/tridemo.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d/triread.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d.egg-info/dependency_links.txt +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d.egg-info/requires.txt +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/bluemesh2d.egg-info/top_level.txt +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/pyproject.toml +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/setup.cfg +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/README.md +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/__init__.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/_cases.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/conftest.py +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/reference/demo0_basic.npz +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/reference/demo0_hfun.npz +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/reference/demo6_internal.npz +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/reference/smood_square.npz +0 -0
- {bluemesh2d-0.1.1.dev0 → bluemesh2d-0.1.2}/tests/regenerate_references.py +0 -0
- {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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bluemesh2d
|
|
3
|
-
Version: 0.1.
|
|
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.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 1,
|
|
21
|
+
__version__ = version = '0.1.2'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 1, 2)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g23470bb1a'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: bluemesh2d
|
|
3
|
-
Version: 0.1.
|
|
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
|
}
|
|
@@ -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)
|