bluemesh2d 0.1.1.dev0__py3-none-any.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.
- bluemesh2d/_version.py +24 -0
- bluemesh2d/aabb_tree/findball.py +121 -0
- bluemesh2d/aabb_tree/findtria.py +299 -0
- bluemesh2d/aabb_tree/maketree.py +147 -0
- bluemesh2d/aabb_tree/mapvert.py +72 -0
- bluemesh2d/aabb_tree/queryset.py +83 -0
- bluemesh2d/aabb_tree/scantree.py +124 -0
- bluemesh2d/dependencies.py +83 -0
- bluemesh2d/feedback.py +142 -0
- bluemesh2d/geom_util/boundary_util.py +216 -0
- bluemesh2d/geom_util/getiso.py +194 -0
- bluemesh2d/geom_util/poly_util.py +795 -0
- bluemesh2d/geom_util/proj_util.py +250 -0
- bluemesh2d/geomesh_util/border_util.py +283 -0
- bluemesh2d/geomesh_util/depth_field.py +333 -0
- bluemesh2d/geomesh_util/grd_util.py +1000 -0
- bluemesh2d/geomesh_util/interpolation_mesh.py +318 -0
- bluemesh2d/geomesh_util/merge_circumcenters.py +268 -0
- bluemesh2d/geomesh_util/water_polygon.py +406 -0
- bluemesh2d/hfun_util/build_hfun.py +589 -0
- bluemesh2d/hfun_util/hfun_dispersion.py +96 -0
- bluemesh2d/hfun_util/lfshfn.py +110 -0
- bluemesh2d/hfun_util/limhfn.py +65 -0
- bluemesh2d/hfun_util/make_constant_hfun.py +32 -0
- bluemesh2d/hfun_util/make_depth_hfun.py +51 -0
- bluemesh2d/hfun_util/smooth_and_precomput.py +188 -0
- bluemesh2d/hfun_util/trihfn.py +84 -0
- bluemesh2d/hjac_util/limgrad.py +105 -0
- bluemesh2d/mesh_ball/cdtbal1.py +38 -0
- bluemesh2d/mesh_ball/cdtbal2.py +104 -0
- bluemesh2d/mesh_ball/inv_2x2.py +61 -0
- bluemesh2d/mesh_ball/inv_3x3.py +72 -0
- bluemesh2d/mesh_ball/pwrbal2.py +134 -0
- bluemesh2d/mesh_ball/tribal2.py +27 -0
- bluemesh2d/mesh_cost/relhfn.py +62 -0
- bluemesh2d/mesh_cost/triang.py +59 -0
- bluemesh2d/mesh_cost/triarea.py +51 -0
- bluemesh2d/mesh_cost/trideg.py +44 -0
- bluemesh2d/mesh_cost/triscr.py +43 -0
- bluemesh2d/mesh_file/bnd_util.py +664 -0
- bluemesh2d/mesh_file/loadmsh.py +165 -0
- bluemesh2d/mesh_file/ugrid.py +308 -0
- bluemesh2d/mesh_util/cfmtri.py +118 -0
- bluemesh2d/mesh_util/deltri.py +131 -0
- bluemesh2d/mesh_util/idxtri.py +53 -0
- bluemesh2d/mesh_util/isfeat.py +90 -0
- bluemesh2d/mesh_util/minlen.py +46 -0
- bluemesh2d/mesh_util/setset.py +49 -0
- bluemesh2d/mesh_util/tricon.py +90 -0
- bluemesh2d/mesh_util/tridiv.py +187 -0
- bluemesh2d/meshgen.py +202 -0
- bluemesh2d/ortho_merge/constants.py +27 -0
- bluemesh2d/ortho_merge/geometry.py +64 -0
- bluemesh2d/ortho_merge/ortho_merge_iter.py +812 -0
- bluemesh2d/ortho_merge/orthogonalize.py +2989 -0
- bluemesh2d/pipeline.py +277 -0
- bluemesh2d/poly_data/airfoil.msh +958 -0
- bluemesh2d/poly_data/channel.msh +212 -0
- bluemesh2d/poly_data/islands.msh +13819 -0
- bluemesh2d/poly_data/lake.msh +612 -0
- bluemesh2d/poly_data/river.msh +690 -0
- bluemesh2d/poly_test/inpoly.py +105 -0
- bluemesh2d/poly_test/inpoly_mat.py +104 -0
- bluemesh2d/refine.py +972 -0
- bluemesh2d/smood.py +623 -0
- bluemesh2d/smooth.py +522 -0
- bluemesh2d/tricost.py +426 -0
- bluemesh2d/tridemo.py +723 -0
- bluemesh2d/triread.py +53 -0
- bluemesh2d-0.1.1.dev0.dist-info/METADATA +139 -0
- bluemesh2d-0.1.1.dev0.dist-info/RECORD +74 -0
- bluemesh2d-0.1.1.dev0.dist-info/WHEEL +5 -0
- bluemesh2d-0.1.1.dev0.dist-info/licenses/LICENSE +674 -0
- bluemesh2d-0.1.1.dev0.dist-info/top_level.txt +1 -0
bluemesh2d/pipeline.py
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"""Staged meshing pipeline: single import point for the Python interface.
|
|
2
|
+
|
|
3
|
+
Re-exports every stage of the raster -> coastline -> size function ->
|
|
4
|
+
boundary -> refine/smooth -> UGRID NetCDF workflow from its home module,
|
|
5
|
+
plus the all-in-one facade (:class:`MeshConfig` -> :func:`generate_mesh`
|
|
6
|
+
-> :class:`MeshResult`) defined here.
|
|
7
|
+
|
|
8
|
+
Stage homes
|
|
9
|
+
-----------
|
|
10
|
+
1. ``bluemesh2d.geomesh_util.water_polygon`` -- extract_water_polygon
|
|
11
|
+
2. ``bluemesh2d.hfun_util.build_hfun`` -- build_hfun_raster & co.
|
|
12
|
+
3. ``bluemesh2d.geom_util.boundary_util`` -- resample_boundary, PSLG
|
|
13
|
+
4. ``bluemesh2d.meshgen`` -- mesh_pslg
|
|
14
|
+
5. ``bluemesh2d.mesh_file.ugrid`` -- export_ugrid, read_ugrid_mesh
|
|
15
|
+
6. ``bluemesh2d.mesh_file.bnd_util`` -- boundary conditions, .grd/.pli
|
|
16
|
+
Support: ``bluemesh2d.feedback`` (progress/cancel), ``bluemesh2d.dependencies``.
|
|
17
|
+
"""
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
# pyproj must load before any pip rasterio wheel loads its own libproj
|
|
21
|
+
# (mixing the order breaks pyproj: "TypeError: expected bytes, str found").
|
|
22
|
+
try:
|
|
23
|
+
import pyproj # noqa: F401
|
|
24
|
+
# pyproj loads libproj lazily at the first CRS creation; force it now,
|
|
25
|
+
# before any rasterio wheel loads its own copy
|
|
26
|
+
pyproj.CRS.from_epsg(4326)
|
|
27
|
+
except Exception:
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
from dataclasses import dataclass
|
|
31
|
+
|
|
32
|
+
from .dependencies import ( # noqa: F401
|
|
33
|
+
check_dependencies,
|
|
34
|
+
optional_dependencies,
|
|
35
|
+
smood_dependencies,
|
|
36
|
+
)
|
|
37
|
+
from .feedback import ( # noqa: F401
|
|
38
|
+
MeshCanceled,
|
|
39
|
+
_LogWriter,
|
|
40
|
+
_NullFeedback,
|
|
41
|
+
_SubProgress,
|
|
42
|
+
_available_ram_bytes,
|
|
43
|
+
_check,
|
|
44
|
+
_warn_if_ram_risk,
|
|
45
|
+
)
|
|
46
|
+
from .geom_util.boundary_util import ( # noqa: F401
|
|
47
|
+
_fixed_part_from_z,
|
|
48
|
+
pslg_from_segments,
|
|
49
|
+
resample_boundary,
|
|
50
|
+
)
|
|
51
|
+
from .geom_util.proj_util import _raster_crs # noqa: F401
|
|
52
|
+
from .geomesh_util.water_polygon import ( # noqa: F401
|
|
53
|
+
_corner_vertices,
|
|
54
|
+
_flag_fixed_vertices,
|
|
55
|
+
_prune_nonoriginal_fixed,
|
|
56
|
+
_valid_parts,
|
|
57
|
+
extract_water_polygon,
|
|
58
|
+
)
|
|
59
|
+
from .hfun_util.build_hfun import ( # noqa: F401
|
|
60
|
+
_compile_custom_hfun,
|
|
61
|
+
_make_depth_hfun,
|
|
62
|
+
build_hfun_constant_raster,
|
|
63
|
+
build_hfun_raster,
|
|
64
|
+
load_hfun_raster,
|
|
65
|
+
)
|
|
66
|
+
from .mesh_file.bnd_util import ( # noqa: F401
|
|
67
|
+
_boundary_loops,
|
|
68
|
+
boundary_lines_from_points,
|
|
69
|
+
classify_boundary_lines,
|
|
70
|
+
classify_boundary_points,
|
|
71
|
+
export_boundary_conditions,
|
|
72
|
+
export_grd,
|
|
73
|
+
export_grd_from_lines,
|
|
74
|
+
generate_boundary_condition_points,
|
|
75
|
+
generate_boundary_conditions,
|
|
76
|
+
write_open_boundary_files,
|
|
77
|
+
write_open_boundary_pli,
|
|
78
|
+
)
|
|
79
|
+
from .mesh_file.ugrid import ( # noqa: F401
|
|
80
|
+
_UGRID_FILL,
|
|
81
|
+
_WGS84_FILL,
|
|
82
|
+
_write_ugrid_netcdf,
|
|
83
|
+
apply_nc_metadata,
|
|
84
|
+
export_ugrid,
|
|
85
|
+
read_ugrid_mesh,
|
|
86
|
+
)
|
|
87
|
+
from .meshgen import ( # noqa: F401
|
|
88
|
+
_locate_fixed,
|
|
89
|
+
_warn_if_mesh_too_big,
|
|
90
|
+
mesh_pslg,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@dataclass
|
|
95
|
+
class MeshConfig:
|
|
96
|
+
"""All tunable parameters of the full meshing pipeline (all-in-one run).
|
|
97
|
+
|
|
98
|
+
Attributes
|
|
99
|
+
----------
|
|
100
|
+
raster_path : str
|
|
101
|
+
Path to the bathymetry raster (elevation, positive up).
|
|
102
|
+
output_path : str
|
|
103
|
+
Output UGRID NetCDF path.
|
|
104
|
+
coast_zmax : float
|
|
105
|
+
Wet threshold (m), see :func:`extract_water_polygon`. Default 2.0.
|
|
106
|
+
domain_buffer : float
|
|
107
|
+
Domain buffer factor, see :func:`extract_water_polygon`.
|
|
108
|
+
Default -0.05.
|
|
109
|
+
keep_largest : bool
|
|
110
|
+
Keep only the largest water polygon. Default ``True``.
|
|
111
|
+
detail_geom : shapely.geometry.base.BaseGeometry or None
|
|
112
|
+
Detail-region polygon in the raster CRS. Default ``None``.
|
|
113
|
+
detail_hmin : float
|
|
114
|
+
Element-size floor (m) inside `detail_geom`. Default 30.0.
|
|
115
|
+
a, b : float
|
|
116
|
+
Depth-polynomial sizing coefficients, see
|
|
117
|
+
:func:`_make_depth_hfun`. Defaults 0.14 and 28.0.
|
|
118
|
+
hmin, hmax : float
|
|
119
|
+
Element-size floor and cap (m). Defaults 100.0 and 10000.0.
|
|
120
|
+
max_gradient : float
|
|
121
|
+
Maximum allowed size gradient (m/m). Default 0.1.
|
|
122
|
+
min_angle_deg : float
|
|
123
|
+
Minimum boundary angle (deg), see :func:`resample_boundary`.
|
|
124
|
+
Default 25.0.
|
|
125
|
+
min_hole_vertices : int
|
|
126
|
+
Minimum hole vertex count, see :func:`resample_boundary`. Default 15.
|
|
127
|
+
kind : {'delaunay', 'delfront'}
|
|
128
|
+
Refinement scheme. Default ``'delaunay'``.
|
|
129
|
+
do_smooth : bool
|
|
130
|
+
Run mesh smoothing after refinement. Default ``True``.
|
|
131
|
+
do_smood : bool
|
|
132
|
+
Run smood orthogonalization after smoothing. Default ``False``.
|
|
133
|
+
smood_merge_small_links : bool
|
|
134
|
+
Enable small-link merging inside smood, see :func:`mesh_pslg`.
|
|
135
|
+
Default ``False``.
|
|
136
|
+
interp_order : int
|
|
137
|
+
Bathymetry sampling order (0=nearest, 1=bilinear, 3=bicubic).
|
|
138
|
+
Default 3.
|
|
139
|
+
"""
|
|
140
|
+
|
|
141
|
+
raster_path: str
|
|
142
|
+
output_path: str
|
|
143
|
+
|
|
144
|
+
coast_zmax: float = 2.0
|
|
145
|
+
domain_buffer: float = -0.05
|
|
146
|
+
keep_largest: bool = True
|
|
147
|
+
|
|
148
|
+
detail_geom: object = None # shapely polygon in the raster CRS
|
|
149
|
+
detail_hmin: float = 30.0
|
|
150
|
+
|
|
151
|
+
a: float = 0.14
|
|
152
|
+
b: float = 28.0
|
|
153
|
+
hmin: float = 100.0
|
|
154
|
+
hmax: float = 10000.0
|
|
155
|
+
max_gradient: float = 0.1
|
|
156
|
+
|
|
157
|
+
min_angle_deg: float = 25.0
|
|
158
|
+
min_hole_vertices: int = 15
|
|
159
|
+
|
|
160
|
+
kind: str = "delaunay" # refine: 'delaunay' | 'delfront'
|
|
161
|
+
do_smooth: bool = True
|
|
162
|
+
do_smood: bool = False
|
|
163
|
+
smood_merge_small_links: bool = False
|
|
164
|
+
|
|
165
|
+
interp_order: int = 3 # bathy sampling: 0=nearest,1=bilinear,3=bicubic
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
@dataclass
|
|
169
|
+
class MeshResult:
|
|
170
|
+
"""Result of a :func:`generate_mesh` run.
|
|
171
|
+
|
|
172
|
+
Attributes
|
|
173
|
+
----------
|
|
174
|
+
output_path : str
|
|
175
|
+
Path to the written UGRID NetCDF.
|
|
176
|
+
n_nodes : int
|
|
177
|
+
Number of mesh nodes.
|
|
178
|
+
n_triangles : int
|
|
179
|
+
Number of mesh triangles.
|
|
180
|
+
utm_crs : str
|
|
181
|
+
String representation of the working CRS used.
|
|
182
|
+
"""
|
|
183
|
+
|
|
184
|
+
output_path: str
|
|
185
|
+
n_nodes: int
|
|
186
|
+
n_triangles: int
|
|
187
|
+
utm_crs: str
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def generate_mesh(config: MeshConfig, feedback=None) -> MeshResult:
|
|
191
|
+
"""Run the full raster -> UGRID-NetCDF meshing pipeline headlessly.
|
|
192
|
+
|
|
193
|
+
Composes stages 1-4 (:func:`extract_water_polygon`, an in-memory
|
|
194
|
+
equivalent of :func:`build_hfun_raster`, :func:`resample_boundary`,
|
|
195
|
+
:func:`mesh_pslg`) and :func:`export_ugrid` in one call.
|
|
196
|
+
|
|
197
|
+
Parameters
|
|
198
|
+
----------
|
|
199
|
+
config : MeshConfig
|
|
200
|
+
Pipeline parameters.
|
|
201
|
+
feedback : object or None, optional
|
|
202
|
+
Feedback sink, see :func:`extract_water_polygon`.
|
|
203
|
+
|
|
204
|
+
Returns
|
|
205
|
+
-------
|
|
206
|
+
result : MeshResult
|
|
207
|
+
Summary of the generated mesh.
|
|
208
|
+
"""
|
|
209
|
+
feedback = feedback or _NullFeedback()
|
|
210
|
+
|
|
211
|
+
missing = check_dependencies()
|
|
212
|
+
if missing:
|
|
213
|
+
raise RuntimeError(
|
|
214
|
+
"Missing Python packages required by BlueMesh2D: "
|
|
215
|
+
+ ", ".join(missing)
|
|
216
|
+
+ ". Install them into this interpreter (see the plugin README).")
|
|
217
|
+
for mod in optional_dependencies():
|
|
218
|
+
feedback.pushInfo(
|
|
219
|
+
f"Optional package '{mod}' not installed - using the built-in "
|
|
220
|
+
"fallback (slower triangulation; install it for best performance).")
|
|
221
|
+
|
|
222
|
+
import pyproj
|
|
223
|
+
from bluemesh2d.geom_util.proj_util import reproject_geometry
|
|
224
|
+
from bluemesh2d.geomesh_util.depth_field import depth_field_from_tif
|
|
225
|
+
from bluemesh2d.hfun_util.smooth_and_precomput import smooth_precomput_hfun
|
|
226
|
+
|
|
227
|
+
feedback.setProgress(2)
|
|
228
|
+
poly, utm_crs, raster_crs = extract_water_polygon(
|
|
229
|
+
config.raster_path, coast_zmax=config.coast_zmax,
|
|
230
|
+
domain_buffer=config.domain_buffer,
|
|
231
|
+
keep_largest=config.keep_largest,
|
|
232
|
+
feedback=_SubProgress(feedback, 2, 25))
|
|
233
|
+
feedback.pushInfo(f"Working CRS: {utm_crs.to_string() if hasattr(utm_crs, 'to_string') else utm_crs}")
|
|
234
|
+
|
|
235
|
+
# In-memory hfun (no raster round-trip needed for the all-in-one run)
|
|
236
|
+
feedback.pushInfo("Building depth-based size function ...")
|
|
237
|
+
feedback.setProgress(25)
|
|
238
|
+
depth_field = depth_field_from_tif(config.raster_path, output_crs=utm_crs)
|
|
239
|
+
detail_u = None
|
|
240
|
+
if config.detail_geom is not None:
|
|
241
|
+
detail_u = reproject_geometry(config.detail_geom, raster_crs, utm_crs)
|
|
242
|
+
hfun = _make_depth_hfun(
|
|
243
|
+
depth_field, a=config.a, b=config.b,
|
|
244
|
+
hmin=config.hmin, hmax=config.hmax,
|
|
245
|
+
detail=detail_u,
|
|
246
|
+
detail_hmin=(config.detail_hmin if detail_u is not None else None))
|
|
247
|
+
|
|
248
|
+
feedback.pushInfo("Gradient-limiting the size function (this can take a moment) ...")
|
|
249
|
+
feedback.setProgress(35)
|
|
250
|
+
# limit the gradient-limiting grid to the water domain (poly is in utm_crs)
|
|
251
|
+
hfuns = smooth_precomput_hfun(hfun, domain=poly, max_gradient=config.max_gradient,
|
|
252
|
+
plot=False)
|
|
253
|
+
_check(feedback)
|
|
254
|
+
|
|
255
|
+
feedback.pushInfo("Resampling boundary to the size function ...")
|
|
256
|
+
feedback.setProgress(45)
|
|
257
|
+
poly_comput, node, edge = resample_boundary(
|
|
258
|
+
poly, hfuns, config.min_angle_deg, config.min_hole_vertices, feedback)
|
|
259
|
+
|
|
260
|
+
feedback.setProgress(55)
|
|
261
|
+
vert, tria = mesh_pslg(node, edge, hfuns, kind=config.kind,
|
|
262
|
+
do_smooth=config.do_smooth,
|
|
263
|
+
do_smood=config.do_smood,
|
|
264
|
+
smood_merge_small_links=config.smood_merge_small_links,
|
|
265
|
+
feedback=_SubProgress(feedback, 55, 88))
|
|
266
|
+
|
|
267
|
+
feedback.setProgress(88)
|
|
268
|
+
export_ugrid(vert, tria, config.raster_path, utm_crs,
|
|
269
|
+
config.output_path, config.interp_order, feedback=feedback)
|
|
270
|
+
feedback.setProgress(100)
|
|
271
|
+
|
|
272
|
+
return MeshResult(
|
|
273
|
+
output_path=config.output_path,
|
|
274
|
+
n_nodes=int(len(vert)),
|
|
275
|
+
n_triangles=int(len(tria)),
|
|
276
|
+
utm_crs=utm_crs.to_string() if hasattr(utm_crs, "to_string") else str(utm_crs),
|
|
277
|
+
)
|