Skip to content

Commit 6528f1c

Browse files
committed
Require a transform context when setting the destination crs for
a feature request Forces correct datum handling for these requests, and removes a few more uses of the deprecated/datum unaware transforms.
1 parent b24a1bf commit 6528f1c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+111
-108
lines changed

python/core/qgsfeaturerequest.sip

+15-1
Original file line numberDiff line numberDiff line change
@@ -549,10 +549,24 @@ and all features will be left with their original geometry.
549549

550550
.. seealso:: :py:func:`setDestinationCrs()`
551551

552+
.. seealso:: :py:func:`transformContext()`
553+
554+
.. versionadded:: 3.0
555+
%End
556+
557+
QgsCoordinateTransformContext transformContext() const;
558+
%Docstring
559+
Returns the transform context, for use when a destinationCrs() has been set
560+
and reprojection is required
561+
562+
.. seealso:: :py:func:`setDestinationCrs()`
563+
564+
.. seealso:: :py:func:`destinationCrs()`
565+
552566
.. versionadded:: 3.0
553567
%End
554568

555-
QgsFeatureRequest &setDestinationCrs( const QgsCoordinateReferenceSystem &crs );
569+
QgsFeatureRequest &setDestinationCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context );
556570
%Docstring
557571
Sets the destination ``crs`` for feature's geometries. If set, all
558572
geometries will be reprojected from their original coordinate reference

python/plugins/processing/algs/qgis/Difference.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def processAlgorithm(self, parameters, context, feedback):
8686
featB = QgsFeature()
8787
outFeat = QgsFeature()
8888

89-
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)
89+
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs(), context.transformContext())), feedback)
9090

9191
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
9292
count = 0
@@ -101,7 +101,7 @@ def processAlgorithm(self, parameters, context, feedback):
101101
attrs = featA.attributes()
102102
intersects = indexB.intersects(geom.boundingBox())
103103
request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
104-
request.setDestinationCrs(sourceA.sourceCrs())
104+
request.setDestinationCrs(sourceA.sourceCrs(), context.transformContext())
105105
for featB in sourceB.getFeatures(request):
106106
if feedback.isCanceled():
107107
break

python/plugins/processing/algs/qgis/HubDistanceLines.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ def processAlgorithm(self, parameters, context, feedback):
114114
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
115115
fields, QgsWkbTypes.LineString, point_source.sourceCrs())
116116

117-
index = QgsSpatialIndex(hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(point_source.sourceCrs())))
117+
index = QgsSpatialIndex(hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(point_source.sourceCrs(), context.transformContext())))
118118

119119
distance = QgsDistanceArea()
120120
distance.setSourceCrs(point_source.sourceCrs())
@@ -133,7 +133,7 @@ def processAlgorithm(self, parameters, context, feedback):
133133
src = f.geometry().boundingBox().center()
134134

135135
neighbors = index.nearestNeighbor(src, 1)
136-
ft = next(hub_source.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], hub_source.fields()).setDestinationCrs(point_source.sourceCrs())))
136+
ft = next(hub_source.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], hub_source.fields()).setDestinationCrs(point_source.sourceCrs(), context.transformContext())))
137137
closest = ft.geometry().boundingBox().center()
138138
hubDist = distance.measureLine(src, closest)
139139

python/plugins/processing/algs/qgis/HubDistancePoints.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ def processAlgorithm(self, parameters, context, feedback):
110110
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
111111
fields, QgsWkbTypes.Point, point_source.sourceCrs())
112112

113-
index = QgsSpatialIndex(hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(point_source.sourceCrs())))
113+
index = QgsSpatialIndex(hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(point_source.sourceCrs(), context.transformContext())))
114114

115115
distance = QgsDistanceArea()
116116
distance.setSourceCrs(point_source.sourceCrs())
@@ -130,7 +130,7 @@ def processAlgorithm(self, parameters, context, feedback):
130130
src = f.geometry().boundingBox().center()
131131

132132
neighbors = index.nearestNeighbor(src, 1)
133-
ft = next(hub_source.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], hub_source.fields()).setDestinationCrs(point_source.sourceCrs())))
133+
ft = next(hub_source.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], hub_source.fields()).setDestinationCrs(point_source.sourceCrs(), context.transformContext())))
134134
closest = ft.geometry().boundingBox().center()
135135
hubDist = distance.measureLine(src, closest)
136136

python/plugins/processing/algs/qgis/HypsometricCurves.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ def processAlgorithm(self, parameters, context, feedback):
114114
memVectorDriver = ogr.GetDriverByName('Memory')
115115
memRasterDriver = gdal.GetDriverByName('MEM')
116116

117-
features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(target_crs))
117+
features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(target_crs, context.transformContext()))
118118
total = 100.0 / source.featureCount() if source.featureCount() else 0
119119

120120
for current, f in enumerate(features):

python/plugins/processing/algs/qgis/Intersection.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def processAlgorithm(self, parameters, context, feedback):
132132
output_fields, geomType, sourceA.sourceCrs())
133133

134134
outFeat = QgsFeature()
135-
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)
135+
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs(), context.transformContext())), feedback)
136136

137137
total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1
138138
count = 0
@@ -149,7 +149,7 @@ def processAlgorithm(self, parameters, context, feedback):
149149
intersects = indexB.intersects(geom.boundingBox())
150150

151151
request = QgsFeatureRequest().setFilterFids(intersects)
152-
request.setDestinationCrs(sourceA.sourceCrs())
152+
request.setDestinationCrs(sourceA.sourceCrs(), context.transformContext())
153153
request.setSubsetOfAttributes(field_indices_b)
154154

155155
engine = None

python/plugins/processing/algs/qgis/PointDistance.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def linearMatrix(self, parameters, context, source, inField, target_source, targ
154154
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
155155
fields, out_wkb, source.sourceCrs())
156156

157-
index = QgsSpatialIndex(target_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(source.sourceCrs())), feedback)
157+
index = QgsSpatialIndex(target_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(source.sourceCrs(), context.transformContext())), feedback)
158158

159159
distArea = QgsDistanceArea()
160160
distArea.setSourceCrs(source.sourceCrs())
@@ -171,7 +171,7 @@ def linearMatrix(self, parameters, context, source, inField, target_source, targ
171171
featList = index.nearestNeighbor(inGeom.asPoint(), nPoints)
172172
distList = []
173173
vari = 0.0
174-
request = QgsFeatureRequest().setFilterFids(featList).setSubsetOfAttributes([outIdx]).setDestinationCrs(source.sourceCrs())
174+
request = QgsFeatureRequest().setFilterFids(featList).setSubsetOfAttributes([outIdx]).setDestinationCrs(source.sourceCrs(), context.transformContext())
175175
for outFeat in target_source.getFeatures(request):
176176
if feedback.isCanceled():
177177
break
@@ -214,7 +214,7 @@ def regularMatrix(self, parameters, context, source, inField, target_source, tar
214214
inIdx = source.fields().lookupField(inField)
215215
targetIdx = target_source.fields().lookupField(targetField)
216216

217-
index = QgsSpatialIndex(target_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(source.sourceCrs())), feedback)
217+
index = QgsSpatialIndex(target_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(source.sourceCrs(), context.transformContext())), feedback)
218218

219219
first = True
220220
sink = None
@@ -233,14 +233,14 @@ def regularMatrix(self, parameters, context, source, inField, target_source, tar
233233
input_id_field = source.fields()[inIdx]
234234
input_id_field.setName('ID')
235235
fields.append(input_id_field)
236-
for f in target_source.getFeatures(QgsFeatureRequest().setFilterFids(featList).setSubsetOfAttributes([targetIdx]).setDestinationCrs(source.sourceCrs())):
236+
for f in target_source.getFeatures(QgsFeatureRequest().setFilterFids(featList).setSubsetOfAttributes([targetIdx]).setDestinationCrs(source.sourceCrs(), context.transformContext())):
237237
fields.append(QgsField(str(f[targetField]), QVariant.Double))
238238

239239
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
240240
fields, source.wkbType(), source.sourceCrs())
241241

242242
data = [inFeat[inField]]
243-
for target in target_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setFilterFids(featList).setDestinationCrs(source.sourceCrs())):
243+
for target in target_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setFilterFids(featList).setDestinationCrs(source.sourceCrs(), context.transformContext())):
244244
if feedback.isCanceled():
245245
break
246246
outGeom = target.geometry()

python/plugins/processing/algs/qgis/PointsFromLines.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ def processAlgorithm(self, parameters, context, feedback):
9797
self.lineId = 0
9898
self.pointId = 0
9999

100-
features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(raster_layer.crs()))
100+
features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(raster_layer.crs(), context.transformContext()))
101101
total = 100.0 / source.featureCount() if source.featureCount() else 0
102102
for current, f in enumerate(features):
103103
if feedback.isCanceled():

python/plugins/processing/algs/qgis/PointsFromPolygons.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def processAlgorithm(self, parameters, context, feedback):
9696
polyId = 0
9797
pointId = 0
9898

99-
features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(raster_layer.crs()))
99+
features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(raster_layer.crs(), context.transformContext()))
100100
total = 100.0 / source.featureCount() if source.featureCount() else 0
101101
for current, f in enumerate(features):
102102
if feedback.isCanceled():

python/plugins/processing/algs/qgis/PointsInPolygon.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ def processAlgorithm(self, parameters, context, feedback):
114114
fields, poly_source.wkbType(), poly_source.sourceCrs())
115115

116116
spatialIndex = QgsSpatialIndex(point_source.getFeatures(
117-
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())), feedback)
117+
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs(), context.transformContext())), feedback)
118118

119119
point_attribute_indices = []
120120
if weight_field_index >= 0:
@@ -140,7 +140,7 @@ def processAlgorithm(self, parameters, context, feedback):
140140

141141
points = spatialIndex.intersects(geom.boundingBox())
142142
if len(points) > 0:
143-
request = QgsFeatureRequest().setFilterFids(points).setDestinationCrs(poly_source.sourceCrs())
143+
request = QgsFeatureRequest().setFilterFids(points).setDestinationCrs(poly_source.sourceCrs(), context.transformContext())
144144
request.setSubsetOfAttributes(point_attribute_indices)
145145
for point_feature in point_source.getFeatures(request):
146146
if feedback.isCanceled():

python/plugins/processing/algs/qgis/ServiceAreaFromLayer.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ def processAlgorithm(self, parameters, context, feedback):
213213

214214
feedback.pushInfo(self.tr('Loading start points...'))
215215
request = QgsFeatureRequest()
216-
request.setDestinationCrs(network.sourceCrs())
216+
request.setDestinationCrs(network.sourceCrs(), context.transformContext())
217217
features = startPoints.getFeatures(request)
218218
total = 100.0 / startPoints.featureCount() if startPoints.featureCount() else 0
219219

python/plugins/processing/algs/qgis/ShortestPathLayerToPoint.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ def processAlgorithm(self, parameters, context, feedback):
215215

216216
feedback.pushInfo(self.tr('Loading start points...'))
217217
request = QgsFeatureRequest()
218-
request.setDestinationCrs(network.sourceCrs())
218+
request.setDestinationCrs(network.sourceCrs(), context.transformContext())
219219
features = startPoints.getFeatures(request)
220220
total = 100.0 / startPoints.featureCount() if startPoints.featureCount() else 0
221221

python/plugins/processing/algs/qgis/ShortestPathPointToLayer.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ def processAlgorithm(self, parameters, context, feedback):
216216

217217
feedback.pushInfo(self.tr('Loading end points...'))
218218
request = QgsFeatureRequest()
219-
request.setDestinationCrs(network.sourceCrs())
219+
request.setDestinationCrs(network.sourceCrs(), context.transformContext())
220220
features = endPoints.getFeatures(request)
221221
total = 100.0 / endPoints.featureCount() if endPoints.featureCount() else 0
222222

python/plugins/processing/algs/qgis/SpatialJoin.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def processAlgorithm(self, parameters, context, feedback):
168168

169169
added_set = set()
170170

171-
request = QgsFeatureRequest().setSubsetOfAttributes(join_field_indexes).setDestinationCrs(source.sourceCrs())
171+
request = QgsFeatureRequest().setSubsetOfAttributes(join_field_indexes).setDestinationCrs(source.sourceCrs(), context.transformContext())
172172
features = join_source.getFeatures(request)
173173
total = 100.0 / join_source.featureCount() if join_source.featureCount() else 0
174174

python/plugins/processing/algs/qgis/SpatialJoinSummary.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ def addField(original, stat, type):
278278

279279
values = []
280280

281-
request = QgsFeatureRequest().setFilterRect(bbox).setSubsetOfAttributes(join_field_indexes).setDestinationCrs(source.sourceCrs())
281+
request = QgsFeatureRequest().setFilterRect(bbox).setSubsetOfAttributes(join_field_indexes).setDestinationCrs(source.sourceCrs(), context.transformContext())
282282
for test_feat in join_source.getFeatures(request):
283283
if feedback.isCanceled():
284284
break

python/plugins/processing/algs/qgis/SumLines.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def processAlgorithm(self, parameters, context, feedback):
104104
fields, poly_source.wkbType(), poly_source.sourceCrs())
105105

106106
spatialIndex = QgsSpatialIndex(line_source.getFeatures(
107-
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())), feedback)
107+
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs(), context.transformContext())), feedback)
108108

109109
distArea = QgsDistanceArea()
110110
distArea.setSourceCrs(poly_source.sourceCrs())
@@ -131,7 +131,7 @@ def processAlgorithm(self, parameters, context, feedback):
131131
engine.prepareGeometry()
132132

133133
if has_intersections:
134-
request = QgsFeatureRequest().setFilterFids(lines).setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())
134+
request = QgsFeatureRequest().setFilterFids(lines).setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs(), context.transformContext())
135135
for line_feature in line_source.getFeatures(request):
136136
if feedback.isCanceled():
137137
break

python/plugins/processing/algs/qgis/SymmetricalDifference.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def processAlgorithm(self, parameters, context, feedback):
9292
outFeat = QgsFeature()
9393

9494
indexA = QgsSpatialIndex(sourceA, feedback)
95-
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)
95+
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs(), context.transformContext())), feedback)
9696

9797
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
9898
count = 0
@@ -106,7 +106,7 @@ def processAlgorithm(self, parameters, context, feedback):
106106
attrs = featA.attributes()
107107
intersects = indexB.intersects(geom.boundingBox())
108108
request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
109-
request.setDestinationCrs(sourceA.sourceCrs())
109+
request.setDestinationCrs(sourceA.sourceCrs(), context.transformContext())
110110
for featB in sourceB.getFeatures(request):
111111
if feedback.isCanceled():
112112
break
@@ -128,7 +128,7 @@ def processAlgorithm(self, parameters, context, feedback):
128128

129129
length = len(sourceA.fields())
130130

131-
for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs())):
131+
for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs(), context.transformContext())):
132132
if feedback.isCanceled():
133133
break
134134

python/plugins/processing/algs/qgis/Union.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def processAlgorithm(self, parameters, context, feedback):
9292
outFeat = QgsFeature()
9393

9494
indexA = QgsSpatialIndex(sourceA, feedback)
95-
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)
95+
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs(), context.transformContext())), feedback)
9696

9797
total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
9898
count = 0
@@ -117,7 +117,7 @@ def processAlgorithm(self, parameters, context, feedback):
117117
feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
118118
else:
119119
request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
120-
request.setDestinationCrs(sourceA.sourceCrs())
120+
request.setDestinationCrs(sourceA.sourceCrs(), context.transformContext())
121121

122122
engine = QgsGeometry.createGeometryEngine(geom.constGet())
123123
engine.prepareGeometry()
@@ -190,7 +190,7 @@ def processAlgorithm(self, parameters, context, feedback):
190190
length = len(sourceA.fields())
191191
atMapA = [None] * length
192192

193-
for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs())):
193+
for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs(), context.transformContext())):
194194
if feedback.isCanceled():
195195
break
196196

@@ -211,7 +211,7 @@ def processAlgorithm(self, parameters, context, feedback):
211211
feedback.pushInfo(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
212212
else:
213213
request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
214-
request.setDestinationCrs(sourceA.sourceCrs())
214+
request.setDestinationCrs(sourceA.sourceCrs(), context.transformContext())
215215

216216
# use prepared geometries for faster intersection tests
217217
engine = QgsGeometry.createGeometryEngine(diff_geom.constGet())

0 commit comments

Comments
 (0)