Skip to content

Commit

Permalink
Require a transform context when setting the destination crs for
Browse files Browse the repository at this point in the history
a feature request

Forces correct datum handling for these requests, and removes
a few more uses of the deprecated/datum unaware transforms.
  • Loading branch information
nyalldawson committed Dec 20, 2017
1 parent b24a1bf commit 6528f1c
Show file tree
Hide file tree
Showing 48 changed files with 111 additions and 108 deletions.
16 changes: 15 additions & 1 deletion python/core/qgsfeaturerequest.sip
Expand Up @@ -549,10 +549,24 @@ and all features will be left with their original geometry.

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

.. seealso:: :py:func:`transformContext()`

.. versionadded:: 3.0
%End

QgsCoordinateTransformContext transformContext() const;
%Docstring
Returns the transform context, for use when a destinationCrs() has been set
and reprojection is required

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

.. seealso:: :py:func:`destinationCrs()`

.. versionadded:: 3.0
%End

QgsFeatureRequest &setDestinationCrs( const QgsCoordinateReferenceSystem &crs );
QgsFeatureRequest &setDestinationCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context );
%Docstring
Sets the destination ``crs`` for feature's geometries. If set, all
geometries will be reprojected from their original coordinate reference
Expand Down
4 changes: 2 additions & 2 deletions python/plugins/processing/algs/qgis/Difference.py
Expand Up @@ -86,7 +86,7 @@ def processAlgorithm(self, parameters, context, feedback):
featB = QgsFeature()
outFeat = QgsFeature()

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

total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount() and sourceB.featureCount() else 1
count = 0
Expand All @@ -101,7 +101,7 @@ def processAlgorithm(self, parameters, context, feedback):
attrs = featA.attributes()
intersects = indexB.intersects(geom.boundingBox())
request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
request.setDestinationCrs(sourceA.sourceCrs())
request.setDestinationCrs(sourceA.sourceCrs(), context.transformContext())
for featB in sourceB.getFeatures(request):
if feedback.isCanceled():
break
Expand Down
4 changes: 2 additions & 2 deletions python/plugins/processing/algs/qgis/HubDistanceLines.py
Expand Up @@ -114,7 +114,7 @@ def processAlgorithm(self, parameters, context, feedback):
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
fields, QgsWkbTypes.LineString, point_source.sourceCrs())

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

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

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

Expand Down
4 changes: 2 additions & 2 deletions python/plugins/processing/algs/qgis/HubDistancePoints.py
Expand Up @@ -110,7 +110,7 @@ def processAlgorithm(self, parameters, context, feedback):
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
fields, QgsWkbTypes.Point, point_source.sourceCrs())

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

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

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

Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/HypsometricCurves.py
Expand Up @@ -114,7 +114,7 @@ def processAlgorithm(self, parameters, context, feedback):
memVectorDriver = ogr.GetDriverByName('Memory')
memRasterDriver = gdal.GetDriverByName('MEM')

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

for current, f in enumerate(features):
Expand Down
4 changes: 2 additions & 2 deletions python/plugins/processing/algs/qgis/Intersection.py
Expand Up @@ -132,7 +132,7 @@ def processAlgorithm(self, parameters, context, feedback):
output_fields, geomType, sourceA.sourceCrs())

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

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

request = QgsFeatureRequest().setFilterFids(intersects)
request.setDestinationCrs(sourceA.sourceCrs())
request.setDestinationCrs(sourceA.sourceCrs(), context.transformContext())
request.setSubsetOfAttributes(field_indices_b)

engine = None
Expand Down
10 changes: 5 additions & 5 deletions python/plugins/processing/algs/qgis/PointDistance.py
Expand Up @@ -154,7 +154,7 @@ def linearMatrix(self, parameters, context, source, inField, target_source, targ
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
fields, out_wkb, source.sourceCrs())

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

distArea = QgsDistanceArea()
distArea.setSourceCrs(source.sourceCrs())
Expand All @@ -171,7 +171,7 @@ def linearMatrix(self, parameters, context, source, inField, target_source, targ
featList = index.nearestNeighbor(inGeom.asPoint(), nPoints)
distList = []
vari = 0.0
request = QgsFeatureRequest().setFilterFids(featList).setSubsetOfAttributes([outIdx]).setDestinationCrs(source.sourceCrs())
request = QgsFeatureRequest().setFilterFids(featList).setSubsetOfAttributes([outIdx]).setDestinationCrs(source.sourceCrs(), context.transformContext())
for outFeat in target_source.getFeatures(request):
if feedback.isCanceled():
break
Expand Down Expand Up @@ -214,7 +214,7 @@ def regularMatrix(self, parameters, context, source, inField, target_source, tar
inIdx = source.fields().lookupField(inField)
targetIdx = target_source.fields().lookupField(targetField)

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

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

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

data = [inFeat[inField]]
for target in target_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setFilterFids(featList).setDestinationCrs(source.sourceCrs())):
for target in target_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setFilterFids(featList).setDestinationCrs(source.sourceCrs(), context.transformContext())):
if feedback.isCanceled():
break
outGeom = target.geometry()
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/PointsFromLines.py
Expand Up @@ -97,7 +97,7 @@ def processAlgorithm(self, parameters, context, feedback):
self.lineId = 0
self.pointId = 0

features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(raster_layer.crs()))
features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(raster_layer.crs(), context.transformContext()))
total = 100.0 / source.featureCount() if source.featureCount() else 0
for current, f in enumerate(features):
if feedback.isCanceled():
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/PointsFromPolygons.py
Expand Up @@ -96,7 +96,7 @@ def processAlgorithm(self, parameters, context, feedback):
polyId = 0
pointId = 0

features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(raster_layer.crs()))
features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(raster_layer.crs(), context.transformContext()))
total = 100.0 / source.featureCount() if source.featureCount() else 0
for current, f in enumerate(features):
if feedback.isCanceled():
Expand Down
4 changes: 2 additions & 2 deletions python/plugins/processing/algs/qgis/PointsInPolygon.py
Expand Up @@ -114,7 +114,7 @@ def processAlgorithm(self, parameters, context, feedback):
fields, poly_source.wkbType(), poly_source.sourceCrs())

spatialIndex = QgsSpatialIndex(point_source.getFeatures(
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())), feedback)
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs(), context.transformContext())), feedback)

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

points = spatialIndex.intersects(geom.boundingBox())
if len(points) > 0:
request = QgsFeatureRequest().setFilterFids(points).setDestinationCrs(poly_source.sourceCrs())
request = QgsFeatureRequest().setFilterFids(points).setDestinationCrs(poly_source.sourceCrs(), context.transformContext())
request.setSubsetOfAttributes(point_attribute_indices)
for point_feature in point_source.getFeatures(request):
if feedback.isCanceled():
Expand Down
Expand Up @@ -213,7 +213,7 @@ def processAlgorithm(self, parameters, context, feedback):

feedback.pushInfo(self.tr('Loading start points...'))
request = QgsFeatureRequest()
request.setDestinationCrs(network.sourceCrs())
request.setDestinationCrs(network.sourceCrs(), context.transformContext())
features = startPoints.getFeatures(request)
total = 100.0 / startPoints.featureCount() if startPoints.featureCount() else 0

Expand Down
Expand Up @@ -215,7 +215,7 @@ def processAlgorithm(self, parameters, context, feedback):

feedback.pushInfo(self.tr('Loading start points...'))
request = QgsFeatureRequest()
request.setDestinationCrs(network.sourceCrs())
request.setDestinationCrs(network.sourceCrs(), context.transformContext())
features = startPoints.getFeatures(request)
total = 100.0 / startPoints.featureCount() if startPoints.featureCount() else 0

Expand Down
Expand Up @@ -216,7 +216,7 @@ def processAlgorithm(self, parameters, context, feedback):

feedback.pushInfo(self.tr('Loading end points...'))
request = QgsFeatureRequest()
request.setDestinationCrs(network.sourceCrs())
request.setDestinationCrs(network.sourceCrs(), context.transformContext())
features = endPoints.getFeatures(request)
total = 100.0 / endPoints.featureCount() if endPoints.featureCount() else 0

Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/SpatialJoin.py
Expand Up @@ -168,7 +168,7 @@ def processAlgorithm(self, parameters, context, feedback):

added_set = set()

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

Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/algs/qgis/SpatialJoinSummary.py
Expand Up @@ -278,7 +278,7 @@ def addField(original, stat, type):

values = []

request = QgsFeatureRequest().setFilterRect(bbox).setSubsetOfAttributes(join_field_indexes).setDestinationCrs(source.sourceCrs())
request = QgsFeatureRequest().setFilterRect(bbox).setSubsetOfAttributes(join_field_indexes).setDestinationCrs(source.sourceCrs(), context.transformContext())
for test_feat in join_source.getFeatures(request):
if feedback.isCanceled():
break
Expand Down
4 changes: 2 additions & 2 deletions python/plugins/processing/algs/qgis/SumLines.py
Expand Up @@ -104,7 +104,7 @@ def processAlgorithm(self, parameters, context, feedback):
fields, poly_source.wkbType(), poly_source.sourceCrs())

spatialIndex = QgsSpatialIndex(line_source.getFeatures(
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())), feedback)
QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs(), context.transformContext())), feedback)

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

if has_intersections:
request = QgsFeatureRequest().setFilterFids(lines).setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())
request = QgsFeatureRequest().setFilterFids(lines).setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs(), context.transformContext())
for line_feature in line_source.getFeatures(request):
if feedback.isCanceled():
break
Expand Down
6 changes: 3 additions & 3 deletions python/plugins/processing/algs/qgis/SymmetricalDifference.py
Expand Up @@ -92,7 +92,7 @@ def processAlgorithm(self, parameters, context, feedback):
outFeat = QgsFeature()

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

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

length = len(sourceA.fields())

for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs())):
for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs(), context.transformContext())):
if feedback.isCanceled():
break

Expand Down
8 changes: 4 additions & 4 deletions python/plugins/processing/algs/qgis/Union.py
Expand Up @@ -92,7 +92,7 @@ def processAlgorithm(self, parameters, context, feedback):
outFeat = QgsFeature()

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

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

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

for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs())):
for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs(sourceA.sourceCrs(), context.transformContext())):
if feedback.isCanceled():
break

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

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

0 comments on commit 6528f1c

Please sign in to comment.