Merge pull request #5919 from nyalldawson/iter_datum

Use transform context in feature requests with destination crs set
This commit is contained in:
Nyall Dawson 2017-12-20 19:02:11 +11:00 committed by GitHub
commit 3c7f745424
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
88 changed files with 242 additions and 187 deletions

View File

@ -1128,7 +1128,8 @@ ellipsoid to 'NONE' to disable ellipsoidal calculations.
- ellipsoidalEnabled() was removed. Ellipsoidal calculations are now enabled whenever a valid ellipsoid() is set. Check
willUseEllipsoid() to determine whether ellipsoidal calculations will be performed.
- sourceCrs() now returns a QgsCoordinateReferenceSystem instead of the crs ID.
- setSourceCrs() now requires a QgsCoordinateReferenceSystem instead of crs ID.
- setSourceCrs() now requires a QgsCoordinateReferenceSystem instead of crs ID, and requires a QgsCoordinateTransformContext object. PyQGIS code
can use QgsProject.instance().transformContext() for the QgsCoordinateTransformContext argument.
- setSourceAuthId() was removed. Use setSourceCrs() instead.
- geographic() was removed. Check sourceCrs().isGeographic() instead.
- measure() has been removed. Use measureArea() or measureLength() instead.

View File

@ -70,6 +70,9 @@ Returns the project in which the algorithm is being executed.
%Docstring
Sets the ``project`` in which the algorithm will be executed.
This also automatically sets the transformContext() to match
the project's transform context.
.. seealso:: :py:func:`project()`
%End
@ -82,6 +85,23 @@ Returns the expression context.
void setExpressionContext( const QgsExpressionContext &context );
%Docstring
Sets the expression ``context``.
%End
QgsCoordinateTransformContext transformContext() const;
%Docstring
Returns the coordinate transform context.
.. seealso:: :py:func:`setTransformContext()`
%End
void setTransformContext( const QgsCoordinateTransformContext &context );
%Docstring
Sets the coordinate transform ``context``.
Note that setting a project for the context will automatically set the coordinate transform
context.
.. seealso:: :py:func:`transformContext()`
%End
QgsMapLayerStore *temporaryLayerStore();

View File

@ -50,9 +50,9 @@ ellipsoid if a valid ellipsoid() has been set.
.. seealso:: :py:func:`ellipsoid()`
%End
void setSourceCrs( const QgsCoordinateReferenceSystem &srcCRS );
void setSourceCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context );
%Docstring
Sets source spatial reference system.
Sets source spatial reference system ``crs``.
.. versionadded:: 2.2

View File

@ -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
QgsFeatureRequest &setDestinationCrs( const QgsCoordinateReferenceSystem &crs );
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, const QgsCoordinateTransformContext &context );
%Docstring
Sets the destination ``crs`` for feature's geometries. If set, all
geometries will be reprojected from their original coordinate reference

View File

@ -10,7 +10,6 @@
class QgsAttributeEditorContext
{
%Docstring

View File

@ -135,7 +135,7 @@ class Aggregate(QgisAlgorithm):
aggregates = self.parameterAsAggregates(parameters, self.AGGREGATES, context)
da = QgsDistanceArea()
da.setSourceCrs(source.sourceCrs())
da.setSourceCrs(source.sourceCrs(), context.transformContext())
da.setEllipsoid(context.project().ellipsoid())
self.source = source

View File

@ -86,7 +86,7 @@ class Difference(QgisAlgorithm):
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
@ -101,7 +101,7 @@ class Difference(QgisAlgorithm):
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

View File

@ -123,7 +123,7 @@ class ExportGeometryInfo(QgisAlgorithm):
self.distance_area = QgsDistanceArea()
if method == 2:
self.distance_area.setSourceCrs(source.sourceCrs())
self.distance_area.setSourceCrs(source.sourceCrs(), context.transformContext())
self.distance_area.setEllipsoid(context.project().ellipsoid())
elif method == 1:
coordTransform = QgsCoordinateTransform(source.sourceCrs(), context.project().crs(), context.project())

View File

@ -104,7 +104,7 @@ class FieldsCalculator(QgisAlgorithm):
expression = QgsExpression(formula)
da = QgsDistanceArea()
da.setSourceCrs(source.sourceCrs())
da.setSourceCrs(source.sourceCrs(), context.transformContext())
da.setEllipsoid(context.project().ellipsoid())
expression.setGeomCalculator(da)

View File

@ -121,7 +121,7 @@ class FieldsMapper(QgisFeatureBasedAlgorithm):
self.expressions = []
da = QgsDistanceArea()
da.setSourceCrs(source.sourceCrs())
da.setSourceCrs(source.sourceCrs(), context.transformContext())
da.setEllipsoid(context.project().ellipsoid())
# create an expression context using thread safe processing context

View File

@ -114,10 +114,10 @@ class HubDistanceLines(QgisAlgorithm):
(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())
distance.setSourceCrs(point_source.sourceCrs(), context.transformContext())
distance.setEllipsoid(context.project().ellipsoid())
# Scan source points, find nearest hub, and write to output file
@ -133,7 +133,7 @@ class HubDistanceLines(QgisAlgorithm):
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)

View File

@ -110,10 +110,10 @@ class HubDistancePoints(QgisAlgorithm):
(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())
distance.setSourceCrs(point_source.sourceCrs(), context.transformContext())
distance.setEllipsoid(context.project().ellipsoid())
# Scan source points, find nearest hub, and write to output file
@ -130,7 +130,7 @@ class HubDistancePoints(QgisAlgorithm):
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)

View File

@ -114,7 +114,7 @@ class HypsometricCurves(QgisAlgorithm):
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):

View File

@ -132,7 +132,7 @@ class Intersection(QgisAlgorithm):
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
@ -149,7 +149,7 @@ class Intersection(QgisAlgorithm):
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

View File

@ -98,7 +98,7 @@ class NearestNeighbourAnalysis(QgisAlgorithm):
spatialIndex = QgsSpatialIndex(source, feedback)
distance = QgsDistanceArea()
distance.setSourceCrs(source.sourceCrs())
distance.setSourceCrs(source.sourceCrs(), context.transformContext())
distance.setEllipsoid(context.project().ellipsoid())
sumDist = 0.00

View File

@ -154,10 +154,10 @@ class PointDistance(QgisAlgorithm):
(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())
distArea.setSourceCrs(source.sourceCrs(), context.transformContext())
distArea.setEllipsoid(context.project().ellipsoid())
features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([inIdx]))
@ -171,7 +171,7 @@ class PointDistance(QgisAlgorithm):
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
@ -208,13 +208,13 @@ class PointDistance(QgisAlgorithm):
def regularMatrix(self, parameters, context, source, inField, target_source, targetField,
nPoints, feedback):
distArea = QgsDistanceArea()
distArea.setSourceCrs(source.sourceCrs())
distArea.setSourceCrs(source.sourceCrs(), context.transformContext())
distArea.setEllipsoid(context.project().ellipsoid())
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
@ -233,14 +233,14 @@ class PointDistance(QgisAlgorithm):
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()

View File

@ -97,7 +97,7 @@ class PointsFromLines(QgisAlgorithm):
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():

View File

@ -96,7 +96,7 @@ class PointsFromPolygons(QgisAlgorithm):
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():

View File

@ -114,7 +114,7 @@ class PointsInPolygon(QgisAlgorithm):
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:
@ -140,7 +140,7 @@ class PointsInPolygon(QgisAlgorithm):
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():

View File

@ -153,7 +153,7 @@ class PointsToPaths(QgisAlgorithm):
feedback.setProgress(0)
da = QgsDistanceArea()
da.setSourceCrs(source.sourceCrs())
da.setSourceCrs(source.sourceCrs(), context.transformContext())
da.setEllipsoid(context.project().ellipsoid())
current = 0

View File

@ -109,7 +109,7 @@ class RandomPointsAlongLines(QgisAlgorithm):
points = dict()
da = QgsDistanceArea()
da.setSourceCrs(source.sourceCrs())
da.setSourceCrs(source.sourceCrs(), context.transformContext())
da.setEllipsoid(context.project().ellipsoid())
request = QgsFeatureRequest()

View File

@ -127,7 +127,7 @@ class RandomPointsPolygons(QgisAlgorithm):
fields, QgsWkbTypes.Point, source.sourceCrs())
da = QgsDistanceArea()
da.setSourceCrs(source.sourceCrs())
da.setSourceCrs(source.sourceCrs(), context.transformContext())
da.setEllipsoid(context.project().ellipsoid())
total = 100.0 / source.featureCount() if source.featureCount() else 0

View File

@ -213,7 +213,7 @@ class ServiceAreaFromLayer(QgisAlgorithm):
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

View File

@ -215,7 +215,7 @@ class ShortestPathLayerToPoint(QgisAlgorithm):
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

View File

@ -216,7 +216,7 @@ class ShortestPathPointToLayer(QgisAlgorithm):
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

View File

@ -168,7 +168,7 @@ class SpatialJoin(QgisAlgorithm):
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

View File

@ -278,7 +278,7 @@ class SpatialJoinSummary(QgisAlgorithm):
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

View File

@ -104,10 +104,10 @@ class SumLines(QgisAlgorithm):
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())
distArea.setSourceCrs(poly_source.sourceCrs(), context.transformContext())
distArea.setEllipsoid(context.project().ellipsoid())
features = poly_source.getFeatures()
@ -131,7 +131,7 @@ class SumLines(QgisAlgorithm):
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

View File

@ -92,7 +92,7 @@ class SymmetricalDifference(QgisAlgorithm):
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
@ -106,7 +106,7 @@ class SymmetricalDifference(QgisAlgorithm):
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
@ -128,7 +128,7 @@ class SymmetricalDifference(QgisAlgorithm):
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

View File

@ -92,7 +92,7 @@ class Union(QgisAlgorithm):
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
@ -117,7 +117,7 @@ class Union(QgisAlgorithm):
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()
@ -190,7 +190,7 @@ class Union(QgisAlgorithm):
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
@ -211,7 +211,7 @@ class Union(QgisAlgorithm):
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())

View File

@ -57,7 +57,7 @@ void QgsLine3DSymbolEntity::addEntityForSelectedLines( const Qgs3DMapSettings &m
// build the feature request to select features
QgsFeatureRequest req;
req.setDestinationCrs( map.crs() );
req.setDestinationCrs( map.crs(), map.transformContext() );
req.setFilterFids( layer->selectedFeatureIds() );
// build the entity
@ -73,7 +73,7 @@ void QgsLine3DSymbolEntity::addEntityForNotSelectedLines( const Qgs3DMapSettings
// build the feature request to select features
QgsFeatureRequest req;
req.setDestinationCrs( map.crs() );
req.setDestinationCrs( map.crs(), map.transformContext() );
QgsFeatureIds notSelected = layer->allFeatureIds();
notSelected.subtract( layer->selectedFeatureIds() );

View File

@ -151,7 +151,7 @@ void QgsPoint3DSymbolInstancedEntityFactory::addEntityForSelectedPoints( const Q
// build the feature request to select features
QgsFeatureRequest req;
req.setDestinationCrs( map.crs() );
req.setDestinationCrs( map.crs(), map.transformContext() );
req.setFilterFids( layer->selectedFeatureIds() );
req.setSubsetOfAttributes( QgsAttributeList() );
@ -168,7 +168,7 @@ void QgsPoint3DSymbolInstancedEntityFactory::addEntityForNotSelectedPoints( cons
// build the feature request to select features
QgsFeatureRequest req;
req.setDestinationCrs( map.crs() );
req.setDestinationCrs( map.crs(), map.transformContext() );
req.setSubsetOfAttributes( QgsAttributeList() );
QgsFeatureIds notSelected = layer->allFeatureIds();
@ -327,7 +327,7 @@ static Qt3DExtras::QPhongMaterial *phongMaterial( const QgsPoint3DSymbol &symbol
void QgsPoint3DSymbolModelEntityFactory::addEntitiesForSelectedPoints( const Qgs3DMapSettings &map, QgsVectorLayer *layer, const QgsPoint3DSymbol &symbol, QgsPoint3DSymbolEntity *parent )
{
QgsFeatureRequest req;
req.setDestinationCrs( map.crs() );
req.setDestinationCrs( map.crs(), map.transformContext() );
req.setSubsetOfAttributes( QgsAttributeList() );
req.setFilterFids( layer->selectedFeatureIds() );
@ -340,7 +340,7 @@ void QgsPoint3DSymbolModelEntityFactory::addEntitiesForNotSelectedPoints( const
{
// build the feature request to select features
QgsFeatureRequest req;
req.setDestinationCrs( map.crs() );
req.setDestinationCrs( map.crs(), map.transformContext() );
req.setSubsetOfAttributes( QgsAttributeList() );
QgsFeatureIds notSelected = layer->allFeatureIds();
notSelected.subtract( layer->selectedFeatureIds() );

View File

@ -70,7 +70,7 @@ void QgsPolygon3DSymbolEntity::addEntityForSelectedPolygons( const Qgs3DMapSetti
// build the feature request to select features
QgsFeatureRequest req;
req.setDestinationCrs( map.crs() );
req.setDestinationCrs( map.crs(), map.transformContext() );
req.setSubsetOfAttributes( _requiredAttributes( symbol, layer ), layer->fields() );
req.setFilterFids( layer->selectedFeatureIds() );
@ -93,7 +93,7 @@ void QgsPolygon3DSymbolEntity::addEntityForNotSelectedPolygons( const Qgs3DMapSe
// build the feature request to select features
QgsFeatureRequest req;
req.setSubsetOfAttributes( _requiredAttributes( symbol, layer ), layer->fields() );
req.setDestinationCrs( map.crs() );
req.setDestinationCrs( map.crs(), map.transformContext() );
QgsFeatureIds notSelected = layer->allFeatureIds();
notSelected.subtract( layer->selectedFeatureIds() );

View File

@ -20,6 +20,7 @@
#include <QVariant>
#include "qgspoint.h"
#include "qgsproject.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsdistancearea.h"
#include "qgis_analysis.h"
@ -62,7 +63,7 @@ class ANALYSIS_EXPORT QgsGraphBuilderInterface
, mCtfEnabled( ctfEnabled )
, mTopologyTolerance( topologyTolerance )
{
mDa.setSourceCrs( mCrs );
mDa.setSourceCrs( mCrs, QgsProject::instance()->transformContext() );
mDa.setEllipsoid( ellipsoidID );
}

View File

@ -85,7 +85,7 @@ QVariantMap QgsClipAlgorithm::processAlgorithm( const QVariantMap &parameters, Q
// first build up a list of clip geometries
QVector< QgsGeometry > clipGeoms;
QgsFeatureIterator it = maskSource->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QList< int >() ).setDestinationCrs( featureSource->sourceCrs() ) );
QgsFeatureIterator it = maskSource->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QList< int >() ).setDestinationCrs( featureSource->sourceCrs(), context.transformContext() ) );
QgsFeature f;
while ( it.nextFeature( f ) )
{

View File

@ -74,7 +74,7 @@ QStringList QgsLocationBasedAlgorithm::predicateOptionsList() const
<< QObject::tr( "cross" );
}
void QgsLocationBasedAlgorithm::process( QgsFeatureSource *targetSource,
void QgsLocationBasedAlgorithm::process( const QgsProcessingContext &context, QgsFeatureSource *targetSource,
QgsFeatureSource *intersectSource,
const QList< int > &selectedPredicates,
const std::function < void( const QgsFeature & ) > &handleFeatureFunction,
@ -95,7 +95,7 @@ void QgsLocationBasedAlgorithm::process( QgsFeatureSource *targetSource,
disjointSet = targetSource->allFeatureIds();
QgsFeatureIds foundSet;
QgsFeatureRequest request = QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ).setDestinationCrs( targetSource->sourceCrs() );
QgsFeatureRequest request = QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ).setDestinationCrs( targetSource->sourceCrs(), context.transformContext() );
QgsFeatureIterator fIt = intersectSource->getFeatures( request );
double step = intersectSource->featureCount() > 0 ? 100.0 / intersectSource->featureCount() : 1;
int current = 0;
@ -273,7 +273,7 @@ QVariantMap QgsSelectByLocationAlgorithm::processAlgorithm( const QVariantMap &p
{
selectedIds.insert( feature.id() );
};
process( selectLayer, intersectSource.get(), selectedPredicates, addToSelection, true, feedback );
process( context, selectLayer, intersectSource.get(), selectedPredicates, addToSelection, true, feedback );
selectLayer->selectByIds( selectedIds, method );
QVariantMap results;
@ -351,7 +351,7 @@ QVariantMap QgsExtractByLocationAlgorithm::processAlgorithm( const QVariantMap &
QgsFeature f = feature;
sink->addFeature( f, QgsFeatureSink::FastInsert );
};
process( input.get(), intersectSource.get(), selectedPredicates, addToSink, false, feedback );
process( context, input.get(), intersectSource.get(), selectedPredicates, addToSink, false, feedback );
QVariantMap results;
results.insert( QStringLiteral( "OUTPUT" ), dest );

View File

@ -49,7 +49,7 @@ class QgsLocationBasedAlgorithm : public QgsProcessingAlgorithm
void addPredicateParameter();
Predicate reversePredicate( Predicate predicate ) const;
QStringList predicateOptionsList() const;
void process( QgsFeatureSource *targetSource, QgsFeatureSource *intersectSource, const QList<int> &selectedPredicates, const std::function< void( const QgsFeature & )> &handleFeatureFunction, bool onlyRequireTargetIds, QgsFeedback *feedback );
void process( const QgsProcessingContext &context, QgsFeatureSource *targetSource, QgsFeatureSource *intersectSource, const QList<int> &selectedPredicates, const std::function< void( const QgsFeature & )> &handleFeatureFunction, bool onlyRequireTargetIds, QgsFeedback *feedback );
};

View File

@ -220,7 +220,7 @@ QVariantMap QgsJoinWithLinesAlgorithm::processAlgorithm( const QVariantMap &para
hubAttributes << hubFeature.attribute( j );
}
QgsFeatureRequest spokeRequest = QgsFeatureRequest().setDestinationCrs( hubSource->sourceCrs() );
QgsFeatureRequest spokeRequest = QgsFeatureRequest().setDestinationCrs( hubSource->sourceCrs(), context.transformContext() );
spokeRequest.setSubsetOfAttributes( spokeFields2Fetch );
spokeRequest.setFilterExpression( QgsExpression::createFieldEqualityExpression( fieldSpokeName, hubFeature.attribute( fieldHubIndex ) ) );

View File

@ -144,7 +144,7 @@ QVariantMap QgsLineIntersectionAlgorithm::processAlgorithm( const QVariantMap &p
if ( !sink )
return QVariantMap();
QgsSpatialIndex spatialIndex( sourceB->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ).setDestinationCrs( sourceA->sourceCrs() ) ), feedback );
QgsSpatialIndex spatialIndex( sourceB->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ).setDestinationCrs( sourceA->sourceCrs(), context.transformContext() ) ), feedback );
QgsFeature outFeature;
QgsFeatureIterator features = sourceA->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( fieldsAIndices ) );
double step = sourceA->featureCount() > 0 ? 100.0 / sourceA->featureCount() : 1;
@ -170,7 +170,7 @@ QVariantMap QgsLineIntersectionAlgorithm::processAlgorithm( const QVariantMap &p
engine->prepareGeometry();
QgsFeatureRequest request = QgsFeatureRequest().setFilterFids( lines );
request.setDestinationCrs( sourceA->sourceCrs() );
request.setDestinationCrs( sourceA->sourceCrs(), context.transformContext() );
request.setSubsetOfAttributes( fieldsBIndices );
QgsFeature inFeatureB;

View File

@ -195,7 +195,7 @@ QVariantMap QgsMergeVectorAlgorithm::processAlgorithm( const QVariantMap &parame
feedback->pushInfo( QObject::tr( "Packaging layer %1/%2: %3" ).arg( i ).arg( layers.count() ).arg( layer->name() ) );
QgsFeatureIterator it = vl->getFeatures( QgsFeatureRequest().setDestinationCrs( outputCrs ) );
QgsFeatureIterator it = vl->getFeatures( QgsFeatureRequest().setDestinationCrs( outputCrs, context.transformContext() ) );
QgsFeature f;
while ( it.nextFeature( f ) )
{

View File

@ -87,7 +87,7 @@ QVariantMap QgsSplitWithLinesAlgorithm::processAlgorithm( const QVariantMap &par
QMap< QgsFeatureId, QgsGeometry > splitGeoms;
QgsFeatureRequest request;
request.setSubsetOfAttributes( QgsAttributeList() );
request.setDestinationCrs( source->sourceCrs() );
request.setDestinationCrs( source->sourceCrs(), context.transformContext() );
QgsFeatureIterator splitLines = linesSource->getFeatures( request );
QgsFeature aSplitFeature;

View File

@ -8196,7 +8196,7 @@ void QgisApp::selectByForm()
}
QgsDistanceArea myDa;
myDa.setSourceCrs( vlayer->crs() );
myDa.setSourceCrs( vlayer->crs(), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
QgsAttributeEditorContext context;

View File

@ -781,7 +781,7 @@ QgsAttributeDialog *QgisAppInterface::getFeatureForm( QgsVectorLayer *l, QgsFeat
{
QgsDistanceArea myDa;
myDa.setSourceCrs( l->crs() );
myDa.setSourceCrs( l->crs(), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
QgsAttributeEditorContext context;

View File

@ -208,7 +208,7 @@ void QgsAttributeActionPropertiesDialog::init( const QSet<QString> &actionScopes
}
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs() );
myDa.setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
mFieldExpression->setLayer( mLayer );

View File

@ -142,7 +142,7 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *layer, QgsAttr
myDa = new QgsDistanceArea();
myDa->setSourceCrs( mLayer->crs() );
myDa->setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
myDa->setEllipsoid( QgsProject::instance()->ellipsoid() );
mEditorContext.setDistanceArea( *myDa );
@ -621,7 +621,7 @@ void QgsAttributeTableDialog::filterExpressionBuilder()
dlg.setWindowTitle( tr( "Expression Based Filter" ) );
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs() );
myDa.setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
dlg.setGeomCalculator( myDa );
@ -981,7 +981,7 @@ void QgsAttributeTableDialog::setFilterExpression( const QString &filterString,
QgsFeatureIds filteredFeatures;
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs() );
myDa.setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
// parse search string and build parsed tree

View File

@ -207,7 +207,7 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer *layer, QWidget *pare
// field combo and expression button
mSizeFieldExpressionWidget->setLayer( mLayer );
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs() );
myDa.setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
mSizeFieldExpressionWidget->setGeomCalculator( myDa );
@ -939,7 +939,7 @@ QString QgsDiagramProperties::showExpressionBuilder( const QString &initialExpre
dlg.setWindowTitle( tr( "Expression Based Attribute" ) );
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs() );
myDa.setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
dlg.setGeomCalculator( myDa );

View File

@ -57,7 +57,7 @@ QgsAttributeDialog *QgsFeatureAction::newDialog( bool cloneFeature )
QgsDistanceArea myDa;
myDa.setSourceCrs( mLayer->crs() );
myDa.setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
context.setDistanceArea( myDa );

View File

@ -61,7 +61,7 @@ QgsFieldCalculator::QgsFieldCalculator( QgsVectorLayer *vl, QWidget *parent )
connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsFieldCalculator::showHelp );
QgsDistanceArea myDa;
myDa.setSourceCrs( vl->crs() );
myDa.setSourceCrs( vl->crs(), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
builder->setGeomCalculator( myDa );
@ -160,7 +160,7 @@ void QgsFieldCalculator::accept()
// Set up QgsDistanceArea each time we (re-)calculate
QgsDistanceArea myDa;
myDa.setSourceCrs( mVectorLayer->crs() );
myDa.setSourceCrs( mVectorLayer->crs(), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
QString calcString = builder->expressionText();

View File

@ -113,7 +113,7 @@ void QgsLabelingGui::setLayer( QgsMapLayer *mapLayer )
mFieldExpressionWidget->setLayer( mLayer );
QgsDistanceArea da;
da.setSourceCrs( mLayer->crs() );
da.setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
da.setEllipsoid( QgsProject::instance()->ellipsoid() );
mFieldExpressionWidget->setGeomCalculator( da );

View File

@ -182,6 +182,6 @@ void QgsMapToolMeasureAngle::updateSettings()
void QgsMapToolMeasureAngle::configureDistanceArea()
{
QString ellipsoidId = QgsProject::instance()->ellipsoid();
mDa.setSourceCrs( mCanvas->mapSettings().destinationCrs() );
mDa.setSourceCrs( mCanvas->mapSettings().destinationCrs(), QgsProject::instance()->transformContext() );
mDa.setEllipsoid( ellipsoidId );
}

View File

@ -250,7 +250,7 @@ QPointF QgsMapToolOffsetPointSymbol::calculateOffset( const QgsPointXY &startPoi
case QgsUnitTypes::RenderMetersInMapUnits:
{
QgsDistanceArea distanceArea;
distanceArea.setSourceCrs( mCanvas->mapSettings().destinationCrs() );
distanceArea.setSourceCrs( mCanvas->mapSettings().destinationCrs(), QgsProject::instance()->transformContext() );
distanceArea.setEllipsoid( mCanvas->mapSettings().ellipsoid() );
// factor=1.0 / 1 meter in MapUnits
factor = 1.0 / distanceArea.measureLineProjected( startPoint );

View File

@ -105,7 +105,7 @@ void QgsMeasureDialog::updateSettings()
// Configure QgsDistanceArea
mDistanceUnits = QgsProject::instance()->distanceUnits();
mAreaUnits = QgsProject::instance()->areaUnits();
mDa.setSourceCrs( mTool->canvas()->mapSettings().destinationCrs() );
mDa.setSourceCrs( mTool->canvas()->mapSettings().destinationCrs(), QgsProject::instance()->transformContext() );
mDa.setEllipsoid( QgsProject::instance()->ellipsoid() );
mTable->clear();

View File

@ -530,14 +530,14 @@ void QgsComposerHtml::setExpressionContext( const QgsFeature &feature, QgsVector
//setup distance area conversion
if ( layer )
{
mDistanceArea->setSourceCrs( layer->crs() );
mDistanceArea->setSourceCrs( layer->crs(), mComposition->project()->transformContext() );
}
else if ( mComposition )
{
//set to composition's mapsettings' crs
QgsComposerMap *referenceMap = mComposition->referenceMap();
if ( referenceMap )
mDistanceArea->setSourceCrs( referenceMap->crs() );
mDistanceArea->setSourceCrs( referenceMap->crs(), mComposition->project()->transformContext() );
}
if ( mComposition )
{

View File

@ -260,14 +260,14 @@ void QgsComposerLabel::refreshExpressionContext()
//setup distance area conversion
if ( layer )
{
mDistanceArea->setSourceCrs( layer->crs() );
mDistanceArea->setSourceCrs( layer->crs(), mComposition->project()->transformContext() );
}
else
{
//set to composition's reference map's crs
QgsComposerMap *referenceMap = mComposition->referenceMap();
if ( referenceMap )
mDistanceArea->setSourceCrs( referenceMap->crs() );
mDistanceArea->setSourceCrs( referenceMap->crs(), mComposition->project()->transformContext() );
}
mDistanceArea->setEllipsoid( mComposition->project()->ellipsoid() );
contentChanged();

View File

@ -337,7 +337,7 @@ double QgsComposerScaleBar::mapWidth() const
else
{
QgsDistanceArea da;
da.setSourceCrs( mComposerMap->crs() );
da.setSourceCrs( mComposerMap->crs(), mComposition->project()->transformContext() );
da.setEllipsoid( mComposition->project()->ellipsoid() );
QgsUnitTypes::DistanceUnit units = da.lengthUnits();

View File

@ -487,7 +487,7 @@ void QgsLayoutItemHtml::setExpressionContext( const QgsFeature &feature, QgsVect
//setup distance area conversion
if ( layer )
{
mDistanceArea.setSourceCrs( layer->crs() );
mDistanceArea.setSourceCrs( layer->crs(), mLayout->project()->transformContext() );
}
else if ( mLayout )
{

View File

@ -250,7 +250,7 @@ void QgsLayoutItemLabel::refreshExpressionContext()
//setup distance area conversion
if ( layer )
{
mDistanceArea->setSourceCrs( layer->crs() );
mDistanceArea->setSourceCrs( layer->crs(), mLayout->project()->transformContext() );
}
else
{

View File

@ -301,7 +301,7 @@ double QgsLayoutItemScaleBar::mapWidth() const
else
{
QgsDistanceArea da;
da.setSourceCrs( mMap->crs() );
da.setSourceCrs( mMap->crs(), mLayout->project()->transformContext() );
da.setEllipsoid( mLayout->project()->ellipsoid() );
QgsUnitTypes::DistanceUnit units = da.lengthUnits();

View File

@ -74,6 +74,7 @@ class CORE_EXPORT QgsProcessingContext
{
mFlags = other.mFlags;
mProject = other.mProject;
mTransformContext = other.mTransformContext;
mExpressionContext = other.mExpressionContext;
mInvalidGeometryCallback = other.mInvalidGeometryCallback;
mInvalidGeometryCheck = other.mInvalidGeometryCheck;
@ -102,9 +103,18 @@ class CORE_EXPORT QgsProcessingContext
/**
* Sets the \a project in which the algorithm will be executed.
*
* This also automatically sets the transformContext() to match
* the project's transform context.
*
* \see project()
*/
void setProject( QgsProject *project ) { mProject = project; }
void setProject( QgsProject *project )
{
mProject = project;
if ( mProject )
mTransformContext = mProject->transformContext();
}
/**
* Returns the expression context.
@ -121,6 +131,22 @@ class CORE_EXPORT QgsProcessingContext
*/
void setExpressionContext( const QgsExpressionContext &context ) { mExpressionContext = context; }
/**
* Returns the coordinate transform context.
* \see setTransformContext()
*/
QgsCoordinateTransformContext transformContext() const { return mTransformContext; }
/**
* Sets the coordinate transform \a context.
*
* Note that setting a project for the context will automatically set the coordinate transform
* context.
*
* \see transformContext()
*/
void setTransformContext( const QgsCoordinateTransformContext &context ) { mTransformContext = context; }
/**
* Returns a reference to the layer store used for storing temporary layers during
* algorithm execution.
@ -375,6 +401,7 @@ class CORE_EXPORT QgsProcessingContext
QgsProcessingContext::Flags mFlags = nullptr;
QPointer< QgsProject > mProject;
QgsCoordinateTransformContext mTransformContext;
//! Temporary project owned by the context, used for storing temporarily loaded map layers
QgsMapLayerStore tempLayerStore;
QgsExpressionContext mExpressionContext;

View File

@ -30,9 +30,7 @@ QgsMemoryFeatureIterator::QgsMemoryFeatureIterator( QgsMemoryFeatureSource *sour
{
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs )
{
Q_NOWARN_DEPRECATED_PUSH
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{

View File

@ -23,9 +23,7 @@ QgsCachedFeatureIterator::QgsCachedFeatureIterator( QgsVectorLayerCache *vlCache
{
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mVectorLayerCache->sourceCrs() )
{
Q_NOWARN_DEPRECATED_PUSH
mTransform = QgsCoordinateTransform( mVectorLayerCache->sourceCrs(), mRequest.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
mTransform = QgsCoordinateTransform( mVectorLayerCache->sourceCrs(), mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{
@ -111,9 +109,7 @@ QgsCachedFeatureWriterIterator::QgsCachedFeatureWriterIterator( QgsVectorLayerCa
{
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mVectorLayerCache->sourceCrs() )
{
Q_NOWARN_DEPRECATED_PUSH
mTransform = QgsCoordinateTransform( mVectorLayerCache->sourceCrs(), mRequest.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
mTransform = QgsCoordinateTransform( mVectorLayerCache->sourceCrs(), mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{

View File

@ -44,7 +44,8 @@ QgsDistanceArea::QgsDistanceArea()
mSemiMajor = -1.0;
mSemiMinor = -1.0;
mInvFlattening = -1.0;
setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( GEOCRS_ID ) ); // WGS 84
QgsCoordinateTransformContext context; // this is ok - by default we have a source/dest of WGS84, so no reprojection takes place
setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( GEOCRS_ID ), context ); // WGS 84
setEllipsoid( GEO_NONE );
}
@ -53,8 +54,9 @@ bool QgsDistanceArea::willUseEllipsoid() const
return mEllipsoid != GEO_NONE;
}
void QgsDistanceArea::setSourceCrs( const QgsCoordinateReferenceSystem &srcCRS )
void QgsDistanceArea::setSourceCrs( const QgsCoordinateReferenceSystem &srcCRS, const QgsCoordinateTransformContext &context )
{
mCoordTransform.setContext( context );
mCoordTransform.setSourceCrs( srcCRS );
}

View File

@ -62,11 +62,11 @@ class CORE_EXPORT QgsDistanceArea
bool willUseEllipsoid() const;
/**
* Sets source spatial reference system.
* Sets source spatial reference system \a crs.
* \since QGIS 2.2
* \see sourceCrs()
*/
void setSourceCrs( const QgsCoordinateReferenceSystem &srcCRS );
void setSourceCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context );
/**
* Returns the source spatial reference system.

View File

@ -243,9 +243,15 @@ QgsCoordinateReferenceSystem QgsFeatureRequest::destinationCrs() const
return mCrs;
}
QgsFeatureRequest &QgsFeatureRequest::setDestinationCrs( const QgsCoordinateReferenceSystem &crs )
QgsCoordinateTransformContext QgsFeatureRequest::transformContext() const
{
return mTransformContext;
}
QgsFeatureRequest &QgsFeatureRequest::setDestinationCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context )
{
mCrs = crs;
mTransformContext = context;
return *this;
}

View File

@ -522,10 +522,20 @@ class CORE_EXPORT QgsFeatureRequest
* or an invalid QgsCoordinateReferenceSystem if no reprojection will be done
* and all features will be left with their original geometry.
* \see setDestinationCrs()
* \see transformContext()
* \since QGIS 3.0
*/
QgsCoordinateReferenceSystem destinationCrs() const;
/**
* Returns the transform context, for use when a destinationCrs() has been set
* and reprojection is required
* \see setDestinationCrs()
* \see destinationCrs()
* \since QGIS 3.0
*/
QgsCoordinateTransformContext transformContext() const;
/**
* Sets the destination \a crs for feature's geometries. If set, all
* geometries will be reprojected from their original coordinate reference
@ -549,7 +559,7 @@ class CORE_EXPORT QgsFeatureRequest
* \see destinationCrs()
* \since QGIS 3.0
*/
QgsFeatureRequest &setDestinationCrs( const QgsCoordinateReferenceSystem &crs );
QgsFeatureRequest &setDestinationCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context );
/**
* Sets a callback function to use when encountering a transform error when iterating
@ -637,6 +647,7 @@ class CORE_EXPORT QgsFeatureRequest
std::function< void( const QgsFeature & ) > mInvalidGeometryCallback;
std::function< void( const QgsFeature & ) > mTransformErrorCallback;
QgsCoordinateReferenceSystem mCrs;
QgsCoordinateTransformContext mTransformContext;
int mConnectionTimeout = -1;
};

View File

@ -166,7 +166,7 @@ QgsRenderContext QgsRenderContext::fromMapSettings( const QgsMapSettings &mapSet
ctx.setExpressionContext( mapSettings.expressionContext() );
ctx.setSegmentationTolerance( mapSettings.segmentationTolerance() );
ctx.setSegmentationToleranceType( mapSettings.segmentationToleranceType() );
ctx.mDistanceArea.setSourceCrs( mapSettings.destinationCrs() );
ctx.mDistanceArea.setSourceCrs( mapSettings.destinationCrs(), mapSettings.transformContext() );
ctx.mDistanceArea.setEllipsoid( mapSettings.ellipsoid() );
ctx.setTransformContext( mapSettings.transformContext() );
//this flag is only for stopping during the current rendering progress,

View File

@ -115,9 +115,7 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeat
{
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs )
{
Q_NOWARN_DEPRECATED_PUSH
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{
@ -160,7 +158,7 @@ QgsVectorLayerFeatureIterator::QgsVectorLayerFeatureIterator( QgsVectorLayerFeat
// values
if ( mRequest.destinationCrs().isValid() )
{
mProviderRequest.setDestinationCrs( QgsCoordinateReferenceSystem() );
mProviderRequest.setDestinationCrs( QgsCoordinateReferenceSystem(), mRequest.transformContext() );
}
if ( mProviderRequest.flags() & QgsFeatureRequest::SubsetOfAttributes )
@ -617,7 +615,7 @@ void QgsVectorLayerFeatureIterator::prepareExpression( int fieldIdx )
QgsExpression *exp = new QgsExpression( exps[oi].cachedExpression );
QgsDistanceArea da;
da.setSourceCrs( mSource->mCrs );
da.setSourceCrs( mSource->mCrs, QgsProject::instance()->transformContext() );
da.setEllipsoid( QgsProject::instance()->ellipsoid() );
exp->setGeomCalculator( &da );
exp->setDistanceUnits( QgsProject::instance()->distanceUnits() );

View File

@ -173,14 +173,12 @@ bool QgsVectorLayerLabelProvider::prepare( const QgsRenderContext &context, QSet
lyr.xform = &mapSettings.mapToPixel();
lyr.ct = QgsCoordinateTransform();
if ( context.coordinateTransform().isValid() )
// this is context for layer rendering - use its CT as it includes correct datum transform
// this is context for layer rendering
lyr.ct = context.coordinateTransform();
else
{
Q_NOWARN_DEPRECATED_PUSH
// otherwise fall back to creating our own CT - this one may not have the correct datum transform!
lyr.ct = QgsCoordinateTransform( mCrs, mapSettings.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
// otherwise fall back to creating our own CT
lyr.ct = QgsCoordinateTransform( mCrs, mapSettings.destinationCrs(), mapSettings.transformContext() );
}
lyr.ptZero = lyr.xform->toMapCoordinates( 0, 0 );
lyr.ptOne = lyr.xform->toMapCoordinates( 1, 0 );

View File

@ -23,7 +23,7 @@
#include "qgsvectorlayer.h"
#include "qgsvectorlayertools.h"
#include "qgis_gui.h"
#include "qgsproject.h"
/**
* \ingroup gui
@ -81,7 +81,7 @@ class GUI_EXPORT QgsAttributeEditorContext
if ( mLayer )
{
mDistanceArea = distanceArea;
mDistanceArea.setSourceCrs( mLayer->crs() );
mDistanceArea.setSourceCrs( mLayer->crs(), QgsProject::instance()->transformContext() );
}
}

View File

@ -351,7 +351,7 @@ QMap< QString, QString > QgsMapToolIdentify::featureDerivedAttributes( QgsFeatur
QString ellipsoid = QgsProject::instance()->ellipsoid();
QgsDistanceArea calc;
calc.setEllipsoid( ellipsoid );
calc.setSourceCrs( layer->crs() );
calc.setSourceCrs( layer->crs(), QgsProject::instance()->transformContext() );
QgsWkbTypes::Type wkbType = QgsWkbTypes::NoGeometry;
QgsWkbTypes::GeometryType geometryType = QgsWkbTypes::NullGeometry;

View File

@ -41,9 +41,7 @@ QgsAfsFeatureIterator::QgsAfsFeatureIterator( QgsAfsFeatureSource *source, bool
{
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->sharedData()->crs() )
{
Q_NOWARN_DEPRECATED_PUSH
mTransform = QgsCoordinateTransform( mSource->sharedData()->crs(), mRequest.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
mTransform = QgsCoordinateTransform( mSource->sharedData()->crs(), mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{

View File

@ -36,9 +36,7 @@ QgsDb2FeatureIterator::QgsDb2FeatureIterator( QgsDb2FeatureSource *source, bool
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs )
{
Q_NOWARN_DEPRECATED_PUSH
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{

View File

@ -41,9 +41,7 @@ QgsDelimitedTextFeatureIterator::QgsDelimitedTextFeatureIterator( QgsDelimitedTe
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs )
{
Q_NOWARN_DEPRECATED_PUSH
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{

View File

@ -31,9 +31,7 @@ QgsGPXFeatureIterator::QgsGPXFeatureIterator( QgsGPXFeatureSource *source, bool
{
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs )
{
Q_NOWARN_DEPRECATED_PUSH
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{

View File

@ -36,9 +36,7 @@ QgsMssqlFeatureIterator::QgsMssqlFeatureIterator( QgsMssqlFeatureSource *source,
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs )
{
Q_NOWARN_DEPRECATED_PUSH
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{

View File

@ -79,9 +79,7 @@ QgsOgrFeatureIterator::QgsOgrFeatureIterator( QgsOgrFeatureSource *source, bool
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs )
{
Q_NOWARN_DEPRECATED_PUSH
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{

View File

@ -41,7 +41,7 @@ QgsOracleFeatureIterator::QgsOracleFeatureIterator( QgsOracleFeatureSource *sour
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs )
{
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs() );
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{

View File

@ -63,9 +63,7 @@ QgsPostgresFeatureIterator::QgsPostgresFeatureIterator( QgsPostgresFeatureSource
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs )
{
Q_NOWARN_DEPRECATED_PUSH
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{

View File

@ -44,9 +44,7 @@ QgsSpatiaLiteFeatureIterator::QgsSpatiaLiteFeatureIterator( QgsSpatiaLiteFeature
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs )
{
Q_NOWARN_DEPRECATED_PUSH
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{

View File

@ -45,9 +45,7 @@ QgsVirtualLayerFeatureIterator::QgsVirtualLayerFeatureIterator( QgsVirtualLayerF
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs )
{
Q_NOWARN_DEPRECATED_PUSH
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{

View File

@ -815,9 +815,7 @@ QgsWFSFeatureIterator::QgsWFSFeatureIterator( QgsWFSFeatureSource *source,
{
if ( mRequest.destinationCrs().isValid() && mRequest.destinationCrs() != mSource->mCrs )
{
Q_NOWARN_DEPRECATED_PUSH
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs() );
Q_NOWARN_DEPRECATED_POP
mTransform = QgsCoordinateTransform( mSource->mCrs, mRequest.destinationCrs(), mRequest.transformContext() );
}
try
{

View File

@ -26,6 +26,7 @@
#include "qgsgeometryfactory.h"
#include "qgsgeometry.h"
#include "qgis.h"
#include "qgsproject.h"
#include <memory>
class TestQgsDistanceArea: public QObject
@ -76,7 +77,7 @@ void TestQgsDistanceArea::basic()
QCOMPARE( resultA, 5.0 );
// Now, on an ellipsoid. Always less?
daA.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 3006 ) );
daA.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 3006 ), QgsProject::instance()->transformContext() );
daA.setEllipsoid( QStringLiteral( "WGS84" ) );
resultA = daA.measureLine( p1, p2 );
QVERIFY( resultA < 5.0 );
@ -177,7 +178,7 @@ void TestQgsDistanceArea::test_distances()
// Set up DA
QgsDistanceArea myDa;
myDa.setSourceCrs( QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:4030" ) ) );
myDa.setSourceCrs( QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:4030" ) ), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QStringLiteral( "WGS84" ) );
QString myFileName = QStringLiteral( TEST_DATA_DIR ) + "/GeodTest-nano.dat";
@ -216,7 +217,7 @@ void TestQgsDistanceArea::regression13601()
//test regression #13601
QgsDistanceArea calc;
calc.setEllipsoid( QStringLiteral( "NONE" ) );
calc.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 1108L ) );
calc.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 1108L ), QgsProject::instance()->transformContext() );
QgsGeometry geom( QgsGeometryFactory::geomFromWkt( QStringLiteral( "Polygon ((252000 1389000, 265000 1389000, 265000 1385000, 252000 1385000, 252000 1389000))" ) ).release() );
QGSCOMPARENEAR( calc.measureArea( geom ), 52000000, 0.0001 );
}
@ -225,7 +226,7 @@ void TestQgsDistanceArea::collections()
{
//test measuring for collections
QgsDistanceArea myDa;
myDa.setSourceCrs( QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:4030" ) ) );
myDa.setSourceCrs( QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:4030" ) ), QgsProject::instance()->transformContext() );
myDa.setEllipsoid( QStringLiteral( "WGS84" ) );
//collection of lines, should be sum of line length
@ -257,7 +258,7 @@ void TestQgsDistanceArea::measureUnits()
//test regression #13610
QgsDistanceArea calc;
calc.setEllipsoid( QStringLiteral( "NONE" ) );
calc.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 254L ) );
calc.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 254L ), QgsProject::instance()->transformContext() );
QgsUnitTypes::DistanceUnit units;
QgsPointXY p1( 1341683.9854275715, 408256.9562717728 );
QgsPointXY p2( 1349321.7807031618, 408256.9562717728 );
@ -279,7 +280,7 @@ void TestQgsDistanceArea::measureUnits()
void TestQgsDistanceArea::measureAreaAndUnits()
{
QgsDistanceArea da;
da.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 3452 ) );
da.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 3452 ), QgsProject::instance()->transformContext() );
da.setEllipsoid( QStringLiteral( "NONE" ) );
QgsCoordinateReferenceSystem daCRS;
daCRS.createFromSrsId( da.sourceCrs().srsid() );
@ -331,7 +332,7 @@ void TestQgsDistanceArea::measureAreaAndUnits()
poly << ring;
polygon = QgsGeometry::fromPolygonXY( poly );
da.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 27469 ) );
da.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 27469 ), QgsProject::instance()->transformContext() );
da.setEllipsoid( QStringLiteral( "NONE" ) );
// measurement should be in square feet
area = da.measureArea( polygon );
@ -361,7 +362,7 @@ void TestQgsDistanceArea::measureAreaAndUnits()
void TestQgsDistanceArea::emptyPolygon()
{
QgsDistanceArea da;
da.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 3452 ) );
da.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 3452 ), QgsProject::instance()->transformContext() );
da.setEllipsoid( QStringLiteral( "WGS84" ) );
//test that measuring an empty polygon doesn't crash
@ -373,7 +374,7 @@ void TestQgsDistanceArea::regression14675()
//test regression #14675
QgsDistanceArea calc;
calc.setEllipsoid( QStringLiteral( "GRS80" ) );
calc.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 145L ) );
calc.setSourceCrs( QgsCoordinateReferenceSystem::fromSrsId( 145L ), QgsProject::instance()->transformContext() );
QgsGeometry geom( QgsGeometryFactory::geomFromWkt( QStringLiteral( "Polygon ((917593.5791854317067191 6833700.00807378999888897, 917596.43389983859378844 6833700.67099479306489229, 917599.53056440979707986 6833700.78673478215932846, 917593.5791854317067191 6833700.00807378999888897))" ) ).release() );
//lots of tolerance here - the formulas get quite unstable with small areas due to division by very small floats
QGSCOMPARENEAR( calc.measureArea( geom ), 0.833010, 0.03 );
@ -383,7 +384,7 @@ void TestQgsDistanceArea::regression16820()
{
QgsDistanceArea calc;
calc.setEllipsoid( QStringLiteral( "WGS84" ) );
calc.setSourceCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:32634" ) ) );
calc.setSourceCrs( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:32634" ) ), QgsProject::instance()->transformContext() );
QgsGeometry geom( QgsGeometryFactory::geomFromWkt( QStringLiteral( "Polygon ((110250.54038314701756462 5084495.57398066483438015, 110243.46975068224128336 5084507.17200060561299324, 110251.23908144699817058 5084506.68309532757848501, 110251.2394439501222223 5084506.68307251576334238, 110250.54048078990308568 5084495.57553235255181789, 110250.54038314701756462 5084495.57398066483438015))" ) ).release() );
//lots of tolerance here - the formulas get quite unstable with small areas due to division by very small floats
QGSCOMPARENEAR( calc.measureArea( geom ), 43.3280029296875, 0.2 );

View File

@ -1991,7 +1991,7 @@ class TestQgsExpression: public QObject
{
//test calculations with and without geometry calculator set
QgsDistanceArea da;
da.setSourceCrs( QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:3111" ) ) );
da.setSourceCrs( QgsCoordinateReferenceSystem::fromOgcWmsCrs( QStringLiteral( "EPSG:3111" ) ), QgsProject::instance()->transformContext() );
da.setEllipsoid( QStringLiteral( "WGS84" ) );
QgsFeature feat;

View File

@ -20,6 +20,7 @@ from qgis.core import (
QgsFeatureRequest,
QgsFeature,
QgsWkbTypes,
QgsProject,
QgsGeometry,
QgsAbstractFeatureIterator,
QgsExpressionContextScope,
@ -517,7 +518,7 @@ class FeatureSourceTestCase(object):
self.assertEqual(request.acceptFeature(f), f['pk'] in expected)
def testGetFeaturesDestinationCrs(self):
request = QgsFeatureRequest().setDestinationCrs(QgsCoordinateReferenceSystem('epsg:3785'))
request = QgsFeatureRequest().setDestinationCrs(QgsCoordinateReferenceSystem('epsg:3785'), QgsProject.instance().transformContext())
features = {f['pk']: f for f in self.source.getFeatures(request)}
# test that features have been reprojected
self.assertAlmostEqual(features[1].geometry().constGet().x(), -7829322, -5)
@ -532,7 +533,7 @@ class FeatureSourceTestCase(object):
# when destination crs is set, filter rect should be in destination crs
rect = QgsRectangle(-7650000, 10500000, -7200000, 15000000)
request = QgsFeatureRequest().setDestinationCrs(QgsCoordinateReferenceSystem('epsg:3785')).setFilterRect(rect)
request = QgsFeatureRequest().setDestinationCrs(QgsCoordinateReferenceSystem('epsg:3785'), QgsProject.instance().transformContext()).setFilterRect(rect)
features = {f['pk']: f for f in self.source.getFeatures(request)}
self.assertEqual(set(features.keys()), {2, 4})
# test that features have been reprojected
@ -543,7 +544,7 @@ class FeatureSourceTestCase(object):
# bad rect for transform
rect = QgsRectangle(-99999999999, 99999999999, -99999999998, 99999999998)
request = QgsFeatureRequest().setDestinationCrs(QgsCoordinateReferenceSystem('epsg:28356')).setFilterRect(rect)
request = QgsFeatureRequest().setDestinationCrs(QgsCoordinateReferenceSystem('epsg:28356'), QgsProject.instance().transformContext()).setFilterRect(rect)
features = [f for f in self.source.getFeatures(request)]
self.assertFalse(features)

View File

@ -19,8 +19,8 @@ from qgis.core import (QgsGeometry,
QgsPointXY,
QgsDistanceArea,
QgsCoordinateReferenceSystem,
QgsUnitTypes
)
QgsUnitTypes,
QgsProject)
from qgis.testing import start_app, unittest
from qgis.PyQt.QtCore import QLocale
@ -40,7 +40,7 @@ class TestQgsDistanceArea(unittest.TestCase):
# try setting using a CRS object
crs = QgsCoordinateReferenceSystem(3111, QgsCoordinateReferenceSystem.EpsgCrsId)
da.setSourceCrs(crs)
da.setSourceCrs(crs, QgsProject.instance().transformContext())
self.assertEqual(da.sourceCrs().srsid(), crs.srsid())
def testMeasureLine(self):
@ -64,12 +64,12 @@ class TestQgsDistanceArea(unittest.TestCase):
da_3068 = QgsDistanceArea()
da_wsg84 = QgsDistanceArea()
da_3068.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:3068'))
da_3068.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:3068'), QgsProject.instance().transformContext())
if (da_3068.sourceCrs().isGeographic()):
da_3068.setEllipsoid(da_3068.sourceCrs().ellipsoidAcronym())
print(("setting [{}] srid [{}] description [{}]".format(u'Soldner Berlin', da_3068.sourceCrs().authid(), da_3068.sourceCrs().description())))
self.assertEqual(da_3068.sourceCrs().authid(), 'EPSG:3068')
da_wsg84.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4326'))
da_wsg84.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4326'), QgsProject.instance().transformContext())
if (da_wsg84.sourceCrs().isGeographic()):
da_wsg84.setEllipsoid(da_wsg84.sourceCrs().ellipsoidAcronym())
self.assertEqual(da_wsg84.sourceCrs().authid(), 'EPSG:4326')
@ -132,38 +132,38 @@ class TestQgsDistanceArea(unittest.TestCase):
# +-+ +
# checking returned length_mapunits/projected_points of diffferent world points with results from SpatiaLite ST_Project
da_3068 = QgsDistanceArea()
da_3068.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:3068'))
da_3068.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:3068'), QgsProject.instance().transformContext())
if (da_3068.sourceCrs().isGeographic()):
da_3068.setEllipsoid(da_3068.sourceCrs().ellipsoidAcronym())
self.assertEqual(da_3068.sourceCrs().authid(), 'EPSG:3068')
print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:3068', da_3068.sourceCrs().authid(), da_3068.sourceCrs().description(), da_3068.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_3068.lengthUnits()), da_3068.sourceCrs().projectionAcronym(), da_3068.sourceCrs().ellipsoidAcronym())))
da_wsg84 = QgsDistanceArea()
da_wsg84.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4326'))
da_wsg84.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4326'), QgsProject.instance().transformContext())
if (da_wsg84.sourceCrs().isGeographic()):
da_wsg84.setEllipsoid(da_wsg84.sourceCrs().ellipsoidAcronym())
self.assertEqual(da_wsg84.sourceCrs().authid(), 'EPSG:4326')
print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}] ellipsoid[{}]".format(u'EPSG:4326', da_wsg84.sourceCrs().authid(), da_wsg84.sourceCrs().description(), da_wsg84.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_wsg84.lengthUnits()), da_wsg84.sourceCrs().projectionAcronym(), da_wsg84.sourceCrs().ellipsoidAcronym(), da_wsg84.ellipsoid())))
da_4314 = QgsDistanceArea()
da_4314.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4314'))
da_4314.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4314'), QgsProject.instance().transformContext())
if (da_4314.sourceCrs().isGeographic()):
da_4314.setEllipsoid(da_4314.sourceCrs().ellipsoidAcronym())
self.assertEqual(da_4314.sourceCrs().authid(), 'EPSG:4314')
print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:4314', da_4314.sourceCrs().authid(), da_4314.sourceCrs().description(), da_4314.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_4314.lengthUnits()), da_4314.sourceCrs().projectionAcronym(), da_4314.sourceCrs().ellipsoidAcronym())))
da_4805 = QgsDistanceArea()
da_4805.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4805'))
da_4805.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:4805'), QgsProject.instance().transformContext())
if (da_4805.sourceCrs().isGeographic()):
da_4805.setEllipsoid(da_4805.sourceCrs().ellipsoidAcronym())
self.assertEqual(da_4805.sourceCrs().authid(), 'EPSG:4805')
print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:4805', da_4805.sourceCrs().authid(), da_4805.sourceCrs().description(), da_4805.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_4805.lengthUnits()), da_4805.sourceCrs().projectionAcronym(), da_4805.sourceCrs().ellipsoidAcronym())))
# EPSG:5665 unknown, why?
da_5665 = QgsDistanceArea()
da_5665.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:5665'))
da_5665.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:5665'), QgsProject.instance().transformContext())
if (da_5665.sourceCrs().isGeographic()):
da_5665.setEllipsoid(da_5665.sourceCrs().ellipsoidAcronym())
print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:5665', da_5665.sourceCrs().authid(), da_5665.sourceCrs().description(), da_5665.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_5665.lengthUnits()), da_5665.sourceCrs().projectionAcronym(), da_5665.sourceCrs().ellipsoidAcronym())))
#self.assertEqual(da_5665.sourceCrs().authid(), 'EPSG:5665')
da_25833 = QgsDistanceArea()
da_25833.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:25833'))
da_25833.setSourceCrs(QgsCoordinateReferenceSystem.fromOgcWmsCrs('EPSG:25833'), QgsProject.instance().transformContext())
if (da_25833.sourceCrs().isGeographic()):
da_25833.setEllipsoid(da_25833.sourceCrs().ellipsoidAcronym())
print(("setting [{}] srid [{}] description [{}] isGeographic[{}] lengthUnits[{}] projectionAcronym[{}] ellipsoidAcronym[{}]".format(u'EPSG:25833', da_25833.sourceCrs().authid(), da_25833.sourceCrs().description(), da_25833.sourceCrs().isGeographic(), QgsUnitTypes.toString(da_25833.lengthUnits()), da_25833.sourceCrs().projectionAcronym(), da_25833.sourceCrs().ellipsoidAcronym())))
@ -470,7 +470,7 @@ class TestQgsDistanceArea(unittest.TestCase):
"""
da = QgsDistanceArea()
da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(3452))
da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(3452), QgsProject.instance().transformContext())
da.setEllipsoid("NONE")
# We check both the measured length AND the units, in case the logic regarding
@ -496,7 +496,7 @@ class TestQgsDistanceArea(unittest.TestCase):
self.assertAlmostEqual(distance, 133.669, delta=0.01)
# now try with a source CRS which is in feet
da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(27469))
da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(27469), QgsProject.instance().transformContext())
da.setEllipsoid("NONE")
# measurement should be in feet
distance = da.measureLine(QgsPointXY(1, 1), QgsPointXY(2, 3))
@ -527,7 +527,7 @@ class TestQgsDistanceArea(unittest.TestCase):
"""
da = QgsDistanceArea()
da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(3452))
da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(3452), QgsProject.instance().transformContext())
da.setEllipsoid("NONE")
polygon = QgsGeometry.fromPolygonXY(
@ -564,7 +564,7 @@ class TestQgsDistanceArea(unittest.TestCase):
QgsPointXY(1850000, 4423000), QgsPointXY(1851000, 4423000), QgsPointXY(1851000, 4424000), QgsPointXY(1852000, 4424000), QgsPointXY(1852000, 4425000), QgsPointXY(1851000, 4425000), QgsPointXY(1850000, 4423000)
]]
)
da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(27469))
da.setSourceCrs(QgsCoordinateReferenceSystem.fromSrsId(27469), QgsProject.instance().transformContext())
da.setEllipsoid("NONE")
# measurement should be in square feet
area = da.measureArea(polygon)

View File

@ -19,6 +19,7 @@ from qgis.core import (QgsVectorLayer,
QgsFeature,
QgsGeometry,
QgsPointXY,
QgsProject,
QgsFeatureRequest,
QgsWkbTypes,
QgsCoordinateReferenceSystem)
@ -121,7 +122,7 @@ class TestQgsFeatureSource(unittest.TestCase):
self.assertEqual(new_features[id].attributes(), f.attributes())
# materialize with reprojection
request = QgsFeatureRequest().setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3785'))
request = QgsFeatureRequest().setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:3785'), QgsProject.instance().transformContext())
new_layer = layer.materialize(request)
self.assertEqual(new_layer.fields(), layer.fields())
self.assertEqual(new_layer.crs().authid(), 'EPSG:3785')

View File

@ -20,7 +20,8 @@ from qgis.core import (QgsRenderContext,
QgsRectangle, QgsPointXY,
QgsCoordinateReferenceSystem,
QgsMapUnitScale,
QgsUnitTypes)
QgsUnitTypes,
QgsProject)
from qgis.PyQt.QtCore import QSize
from qgis.PyQt.QtGui import QPainter, QImage
from qgis.testing import start_app, unittest
@ -65,7 +66,7 @@ class TestQgsRenderContext(unittest.TestCase):
length_wsg84_mapunits = 0.00001473026350140572
meters_test = 2.40
da_wsg84 = QgsDistanceArea()
da_wsg84.setSourceCrs(crs_wsg84)
da_wsg84.setSourceCrs(crs_wsg84, QgsProject.instance().transformContext())
if (da_wsg84.sourceCrs().isGeographic()):
da_wsg84.setEllipsoid(da_wsg84.sourceCrs().ellipsoidAcronym())
length_meter_mapunits = da_wsg84.measureLineProjected(point_berlin_wsg84, 1.0, (math.pi / 2))

2
tests/src/python/test_qgsvectorlayer.py Normal file → Executable file
View File

@ -2557,7 +2557,7 @@ class TestQgsVectorLayer(unittest.TestCase, FeatureSourceTestCase):
self.assertAlmostEqual(virtual_values[4], -65.32, 2)
# repeat, with reprojection on request
request = QgsFeatureRequest().setDestinationCrs(QgsCoordinateReferenceSystem('epsg:3785'))
request = QgsFeatureRequest().setDestinationCrs(QgsCoordinateReferenceSystem('epsg:3785'), QgsProject.instance().transformContext())
features = [f for f in layer.getFeatures(request)]
# virtual field value should not change, even though geometry has
self.assertAlmostEqual(features[0]['virtual'], -71.123, 2)