1+ import logging
12import os
23import tempfile
3- import warnings
4+ from typing import Optional
45
56import geopandas as gpd
67import numpy as np
2829from qgis .PyQt .QtCore import QDateTime , QVariant
2930from shapely .geometry import LineString , MultiLineString , MultiPoint , MultiPolygon , Point , Polygon
3031
32+ logger = logging .getLogger (__name__ )
33+
3134
3235def qgsRasterToGdalDataset (rlayer : QgsRasterLayer ):
3336 """
@@ -91,12 +94,12 @@ def qgsRasterToGdalDataset(rlayer: QgsRasterLayer):
9194
9295def _get_crs_id (crs ):
9396 """Get a safe string identifier for a CRS.
94-
97+
9598 Parameters
9699 ----------
97100 crs : QgsCoordinateReferenceSystem or None
98101 The CRS to get an ID for
99-
102+
100103 Returns
101104 -------
102105 str
@@ -110,85 +113,81 @@ def _get_crs_id(crs):
110113 return "Unknown"
111114
112115
113- def qgsLayerToGeoDataFrame (layer , target_crs = None ) -> gpd .GeoDataFrame :
116+ def qgsLayerToGeoDataFrame (layer , target_crs = None ) -> Optional [ gpd .GeoDataFrame ] :
114117 """Convert a QgsVectorLayer to a GeoDataFrame, optionally transforming to a target CRS.
115-
118+
116119 Parameters
117120 ----------
118121 layer : QgsVectorLayer
119122 The vector layer to convert
120123 target_crs : QgsCoordinateReferenceSystem, optional
121124 If provided, all geometries will be transformed to this CRS.
122125 If None, the layer's source CRS is used.
123-
126+
124127 Returns
125128 -------
126129 gpd.GeoDataFrame
127130 GeoDataFrame with geometries in the specified CRS
128131 """
129132 if layer is None :
130133 return None
131-
134+
132135 features = layer .getFeatures ()
133136 fields = layer .fields ()
134137 data = {'geometry' : []}
135138 for f in fields :
136139 data [f .name ()] = []
137-
140+
138141 # Set up coordinate transformation if needed
139142 transform = None
140143 source_crs = layer .sourceCrs ()
141144 output_crs = source_crs
142-
145+
143146 if target_crs is not None and target_crs .isValid ():
144147 if source_crs .isValid () and source_crs != target_crs :
145148 transform = QgsCoordinateTransform (source_crs , target_crs , QgsProject .instance ())
146149 output_crs = target_crs
147-
150+
148151 for feature in features :
149152 geom = feature .geometry ()
150153 if geom .isEmpty ():
151154 continue
152-
155+
153156 # Transform geometry if needed
154157 if transform is not None :
155158 geom_copy = QgsGeometry (geom )
156159 try :
157160 result = geom_copy .transform (transform )
158161 if result != 0 :
159162 # Transform returned error code
160- warnings . warn (
163+ logger . warning (
161164 f"Failed to transform geometry (error code { result } ). "
162165 f"Source CRS: { _get_crs_id (source_crs )} , Target CRS: { _get_crs_id (target_crs )} . "
163- f"Skipping feature." ,
164- RuntimeWarning
166+ f"Skipping feature."
165167 )
166168 continue
167- data ['geometry' ].append (geom_copy )
168169 except Exception as e :
169170 # If transformation fails, log warning and skip this feature
170- warnings . warn (
171+ logger . exception (
171172 f"Exception during CRS transformation: { e } . "
172173 f"Source CRS: { _get_crs_id (source_crs )} , Target CRS: { _get_crs_id (target_crs )} . "
173- f"Skipping feature." ,
174- RuntimeWarning
174+ f"Skipping feature."
175175 )
176176 continue
177177 else :
178178 data ['geometry' ].append (geom )
179-
179+
180180 # Copy field values
181181 for f in fields :
182182 if f .type () == QVariant .String :
183183 data [f .name ()].append (str (feature [f .name ()]))
184184 else :
185185 data [f .name ()].append (feature [f .name ()])
186-
187- return gpd .GeoDataFrame (data , crs = output_crs .authid ())
188186
187+ return gpd .GeoDataFrame (data , crs = output_crs .authid ())
189188
190189
191- def qgsLayerToDataFrame (src , dtm = None ) -> pd .DataFrame :
190+ def qgsLayerToDataFrame (src , dtm = None ) -> Optional [ pd .DataFrame ] :
192191 """
193192 Convert a vector layer or processing feature source to a pandas DataFrame.
194193 Samples geometry using points or vertices of lines/polygons.
0 commit comments