Skip to content

Commit d116728

Browse files
committed
Moved Geotiff creation to its own module.
Moved Geotiff creation to its own module. Now the functionality actually creates .tif instead of .pdf. Removed print layout from project.
1 parent 7efd81f commit d116728

File tree

6 files changed

+140
-199
lines changed

6 files changed

+140
-199
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import os
2+
3+
from osgeo import gdal
4+
from qgis.core import QgsMapRendererParallelJob, QgsMapSettings, QgsMapSettingsUtils
5+
from qgis.PyQt.QtCore import QSize
6+
from qgis.PyQt.QtGui import QColor
7+
from qgis.PyQt.QtWidgets import QFileDialog
8+
from qgis.utils import iface
9+
10+
from arho_feature_template.project.layers.plan_layers import (
11+
LandUseAreaLayer,
12+
LandUsePointLayer,
13+
LineLayer,
14+
OtherAreaLayer,
15+
OtherPointLayer,
16+
PlanLayer,
17+
)
18+
from arho_feature_template.utils.misc_utils import get_active_plan_id, use_wait_cursor
19+
20+
21+
class CreateGeoTiff:
22+
def __init__(self, desired_pixel_size=0.5):
23+
"""Initialize the CreateGeoTiff class and fetch the required data."""
24+
self.desired_pixel_size = desired_pixel_size
25+
self.plan_layer = PlanLayer.get_from_project()
26+
27+
if not self.plan_layer:
28+
iface.messageBar().pushWarning("", "No active plan layer found.")
29+
return
30+
31+
self.feature = PlanLayer.get_feature_by_id(get_active_plan_id(), no_geometries=False)
32+
33+
if not self.feature:
34+
iface.messageBar().pushWarning("", "No active feature found.")
35+
return
36+
37+
def select_output_file(self):
38+
"""Opens a file dialog for the user to select the output GeoTIFF file."""
39+
geotiff_path, _ = QFileDialog.getSaveFileName(
40+
None, "Määritä GeoTIFF tallennuspolku", "", "GeoTIFF Files (*.tif)"
41+
)
42+
if not geotiff_path:
43+
iface.messageBar().pushWarning("", "No file selected.")
44+
return None
45+
46+
self.create_geotiff(geotiff_path)
47+
48+
@use_wait_cursor
49+
def create_geotiff(self, geotiff_path):
50+
"""Creates a GeoTIFF from the active plan layer and feature."""
51+
if not self.plan_layer or not self.feature:
52+
return # Stop if there is no valid layer or feature
53+
54+
# **Get Feature Extent + Buffer**
55+
bbox = self.feature.geometry().boundingBox()
56+
buffer_percentage = 0.1
57+
buffer_x = bbox.width() * buffer_percentage
58+
buffer_y = bbox.height() * buffer_percentage
59+
buffered_bbox = bbox.buffered(max(buffer_x, buffer_y))
60+
61+
# **Set Map Rendering Settings**
62+
settings = QgsMapSettings()
63+
settings.setLayers(
64+
[
65+
LandUseAreaLayer.get_from_project(),
66+
OtherAreaLayer.get_from_project(),
67+
LandUsePointLayer.get_from_project(),
68+
LineLayer.get_from_project(),
69+
OtherPointLayer.get_from_project(),
70+
PlanLayer.get_from_project(),
71+
]
72+
)
73+
settings.setBackgroundColor(QColor(255, 255, 255))
74+
settings.setExtent(buffered_bbox)
75+
76+
# **Determine Image Size in Pixels**
77+
pixels_x = int(buffered_bbox.width() / self.desired_pixel_size)
78+
pixels_y = int(buffered_bbox.height() / self.desired_pixel_size)
79+
settings.setOutputSize(QSize(pixels_x, pixels_y))
80+
81+
# **Render Map**
82+
render = QgsMapRendererParallelJob(settings)
83+
84+
def finished():
85+
img = render.renderedImage()
86+
87+
# Save the image as PNG
88+
image_path = geotiff_path.replace(".tif", ".png")
89+
img.save(image_path, "PNG")
90+
91+
# Generate the World File (.pgw)
92+
pgw_content = QgsMapSettingsUtils.worldFileContent(settings)
93+
with open(image_path.replace(".png", ".pgw"), "w") as f:
94+
f.write(pgw_content)
95+
96+
# Convert PNG to GeoTIFF
97+
self._create_geotiff_from_png(image_path, geotiff_path, settings, pixels_x, pixels_y, buffered_bbox)
98+
99+
# **Delete the temporary PNG file**
100+
if os.path.exists(image_path):
101+
os.remove(image_path)
102+
103+
render.finished.connect(finished)
104+
render.start()
105+
106+
def _create_geotiff_from_png(self, image_path, geotiff_path, settings, pixels_x, pixels_y, buffered_bbox):
107+
"""Convert the rendered PNG to GeoTIFF."""
108+
transform = [
109+
buffered_bbox.xMinimum(),
110+
self.desired_pixel_size,
111+
0,
112+
buffered_bbox.yMaximum(),
113+
0,
114+
-self.desired_pixel_size,
115+
]
116+
117+
ds = gdal.Open(image_path)
118+
119+
output_bounds = [
120+
transform[0],
121+
transform[3],
122+
transform[0] + pixels_x * transform[1],
123+
transform[3] + pixels_y * transform[5],
124+
]
125+
126+
# Convert the PNG to GeoTIFF
127+
gdal.Translate(
128+
geotiff_path,
129+
ds,
130+
outputBounds=output_bounds,
131+
outputSRS="EPSG:3067",
132+
format="GTiff",
133+
creationOptions=["COMPRESS=LZW"],
134+
)
135+
136+
iface.messageBar().pushMessage("", f"GeoTIFF tallennettu polkuun: {geotiff_path}")

arho_feature_template/core/plan_manager.py

+1-54
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from collections import defaultdict
66
from typing import TYPE_CHECKING
77

8-
from qgis.core import QgsLayoutExporter, QgsLayoutItemMap, QgsProject, QgsVectorLayer, QgsWkbTypes
8+
from qgis.core import QgsProject, QgsVectorLayer, QgsWkbTypes
99
from qgis.gui import QgsMapToolDigitizeFeature
1010
from qgis.PyQt.QtWidgets import QDialog
1111

@@ -22,7 +22,6 @@
2222
RegulationGroupLibrary,
2323
)
2424
from arho_feature_template.exceptions import UnsavedChangesError
25-
from arho_feature_template.gui.dialogs.create_geotiff import CreateGeoTiff
2625
from arho_feature_template.gui.dialogs.lifecycle_editor import LifecycleEditor
2726
from arho_feature_template.gui.dialogs.load_plan_dialog import LoadPlanDialog
2827
from arho_feature_template.gui.dialogs.plan_attribute_form import PlanAttributeForm
@@ -424,58 +423,6 @@ def save_plan_jsons(self, plan_json, outline_json):
424423

425424
iface.messageBar().pushSuccess("", "Kaava ja kaavan ulkoraja tallennettu.")
426425

427-
def create_geotiff(self):
428-
# Get the plan layer
429-
plan_layer = PlanLayer.get_from_project()
430-
if not plan_layer:
431-
return
432-
433-
# Get the active plan feature
434-
feature = PlanLayer.get_feature_by_id(get_active_plan_id(), no_geometries=False)
435-
if feature is None:
436-
iface.messageBar().pushWarning("", "Mikään kaava ei ole avattuna.")
437-
return
438-
439-
# Open the dialog to get save path
440-
dialog = CreateGeoTiff()
441-
if dialog.exec_() == QDialog.Accepted:
442-
self.geotiff_path = str(dialog.plan_geotiff_file.filePath())
443-
444-
# Get the print layout
445-
manager = QgsProject.instance().layoutManager()
446-
layout = manager.layoutByName("Kaavakartta")
447-
if not layout:
448-
iface.messageBar().pushWarning("", "Tulostusasettelu 'Kaavakartta' ei löytynyt.")
449-
return
450-
451-
# Find the map item in the layout
452-
map_item = next((item for item in layout.items() if isinstance(item, QgsLayoutItemMap)), None)
453-
if not map_item:
454-
iface.messageBar().pushWarning("", "Tulostusasettelussa ei ole karttaobjektia.")
455-
return
456-
457-
# Expand the bounding box by 10%
458-
bbox = feature.geometry().boundingBox()
459-
buffer_percentage = 0.1
460-
buffer_x = bbox.width() * buffer_percentage
461-
buffer_y = bbox.height() * buffer_percentage
462-
buffered_bbox = bbox.buffered(max(buffer_x, buffer_y))
463-
464-
map_item.zoomToExtent(buffered_bbox)
465-
layout.refresh()
466-
467-
# Refresh the layout
468-
layout.refresh()
469-
470-
# Export to PDF
471-
exporter = QgsLayoutExporter(layout)
472-
result = exporter.exportToPdf(self.geotiff_path, QgsLayoutExporter.PdfExportSettings())
473-
474-
if result != QgsLayoutExporter.Success:
475-
iface.messageBar().pushWarning("", "PDF-tiedoston luominen epäonnistui.")
476-
else:
477-
iface.messageBar().pushMessage("", "PDF tallennettu: " + self.geotiff_path)
478-
479426
def unload(self):
480427
# Set pan map tool as active (to deactivate our custom tools to avoid errors)
481428
iface.actionPan().trigger()

arho_feature_template/gui/dialogs/create_geotiff.py

-37
This file was deleted.

arho_feature_template/gui/dialogs/create_geotiff.ui

-107
This file was deleted.

arho_feature_template/plugin.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from qgis.PyQt.QtGui import QIcon
99
from qgis.PyQt.QtWidgets import QAction, QWidget
1010

11+
from arho_feature_template.core.create_geotiff import CreateGeoTiff
1112
from arho_feature_template.core.plan_manager import PlanManager
1213
from arho_feature_template.gui.dialogs.plugin_settings import PluginSettings
1314
from arho_feature_template.gui.docks.validation_dock import ValidationDock
@@ -291,7 +292,8 @@ def edit_lifecycles(self):
291292

292293
def create_geotiff(self):
293294
"""Create geotiff from currently active plan."""
294-
self.plan_manager.create_geotiff()
295+
create_geotiff = CreateGeoTiff()
296+
create_geotiff.select_output_file()
295297

296298
def unload(self) -> None:
297299
"""Removes the plugin menu item and icon from QGIS GUI."""

qgisprojekti.qgz

-158 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)