commit 4360e88195d3a7ba001b866900d7fe367980a3d8
parent 2bb698a6e440dbd9a3091a573dc735b0ae903f30
Author: Anders Damsgaard <anders@adamsgaard.dk>
Date: Fri, 15 May 2026 23:35:19 +0200
feat(qgis): add DEM row adjustment helper
Diffstat:
2 files changed, 115 insertions(+), 0 deletions(-)
diff --git a/tem_loader/tem_loader.py b/tem_loader/tem_loader.py
@@ -130,6 +130,57 @@ def _sample_dem_elevation(raster_layer, source_crs, project, x, y):
return elevation
+def _point_wkt(x, y, z):
+ return f'POINT Z ({x} {y} {z})'
+
+
+def _line_wkt(x, y, z_top, z_bottom):
+ return f'LINESTRING Z ({x} {y} {z_top}, {x} {y} {z_bottom})'
+
+
+def _adjust_rows_to_dem(points, doi_points, layers, raster_layer, source_crs,
+ project):
+ if raster_layer is None:
+ return
+
+ dem_z_by_xy = {}
+ for point in points:
+ x = point['X']
+ y = point['Y']
+ dem_z = _sample_dem_elevation(raster_layer, source_crs, project, x, y)
+ if dem_z is None:
+ continue
+ dem_z_by_xy[(x, y)] = dem_z
+ point['Z'] = dem_z
+ point['Geometry'] = _point_wkt(x, y, dem_z)
+
+ for doi_point in doi_points:
+ x = doi_point['X']
+ y = doi_point['Y']
+ dem_z = dem_z_by_xy.get((x, y))
+ if dem_z is None:
+ continue
+ z_doi = dem_z - doi_point['DOI']
+ doi_point['Z'] = z_doi
+ doi_point['ZDOI'] = z_doi
+ doi_point['Geometry'] = _point_wkt(x, y, z_doi)
+
+ for layer in layers:
+ x = layer['X']
+ y = layer['Y']
+ dem_z = dem_z_by_xy.get((x, y))
+ if dem_z is None:
+ continue
+ z_top = dem_z - layer['DepthTop']
+ z_bottom = dem_z - layer['DepthBottom']
+ z_mid = (z_top + z_bottom) / 2
+ layer['Z'] = dem_z
+ layer['ZTop'] = z_top
+ layer['ZMid'] = z_mid
+ layer['ZBottom'] = z_bottom
+ layer['Geometry'] = _line_wkt(x, y, z_top, z_bottom)
+
+
def _write_geopackage_layer(rows, gpkg_path, layer_name, wkb_type, crs,
transform_context, action):
fields = _build_fields(rows)
diff --git a/test/test_core.py b/test/test_core.py
@@ -1146,6 +1146,70 @@ class PluginTests(unittest.TestCase):
"to DEM raster DEM: bad transform"
)
+ def test_adjust_rows_to_dem_updates_vertical_fields_and_geometry(self):
+ module, _, _ = self._import_plugin_module()
+ provider = Mock()
+ provider.sample.return_value = "123.0", True
+ raster_layer = Mock()
+ raster_layer.crs.return_value = module.QgsCoordinateReferenceSystem(
+ "EPSG:3857"
+ )
+ raster_layer.dataProvider.return_value = provider
+ points = [
+ {
+ "X": 1.0,
+ "Y": 2.0,
+ "Z": 100.0,
+ "Geometry": "POINT Z (1.0 2.0 100.0)",
+ }
+ ]
+ doi_points = [
+ {
+ "X": 1.0,
+ "Y": 2.0,
+ "Z": 90.0,
+ "DOI": 10.0,
+ "ZDOI": 90.0,
+ "Geometry": "POINT Z (1.0 2.0 90.0)",
+ }
+ ]
+ layers = [
+ {
+ "X": 1.0,
+ "Y": 2.0,
+ "Z": 100.0,
+ "DepthTop": 0.0,
+ "DepthBottom": 5.0,
+ "ZTop": 100.0,
+ "ZMid": 97.5,
+ "ZBottom": 95.0,
+ "Geometry": "LINESTRING Z (1.0 2.0 100.0, 1.0 2.0 95.0)",
+ }
+ ]
+
+ module._adjust_rows_to_dem(
+ points,
+ doi_points,
+ layers,
+ raster_layer,
+ module.QgsCoordinateReferenceSystem("EPSG:25832"),
+ module.QgsProject.instance(),
+ )
+
+ self.assertEqual(points[0]["Z"], 123.0)
+ self.assertEqual(points[0]["Geometry"], "POINT Z (1.0 2.0 123.0)")
+ self.assertEqual(doi_points[0]["Z"], 113.0)
+ self.assertEqual(doi_points[0]["ZDOI"], 113.0)
+ self.assertEqual(doi_points[0]["Geometry"], "POINT Z (1.0 2.0 113.0)")
+ self.assertEqual(layers[0]["Z"], 123.0)
+ self.assertEqual(layers[0]["ZTop"], 123.0)
+ self.assertEqual(layers[0]["ZMid"], 120.5)
+ self.assertEqual(layers[0]["ZBottom"], 118.0)
+ self.assertEqual(
+ layers[0]["Geometry"],
+ "LINESTRING Z (1.0 2.0 123.0, 1.0 2.0 118.0)",
+ )
+
def test_exec_dialog_supports_exec_and_exec_apis(self):
module, _, _ = self._import_plugin_module()
exec_dialog = Mock()