Skip to content

Commit

Permalink
Merge pull request #5201 from nyalldawson/point_crs
Browse files Browse the repository at this point in the history
[processing] Transparently handle CRS for point parameters
  • Loading branch information
alexbruy committed Sep 25, 2017
2 parents f4d5ca7 + d72309e commit 14a48c0
Show file tree
Hide file tree
Showing 16 changed files with 473 additions and 68 deletions.
16 changes: 15 additions & 1 deletion python/core/processing/qgsprocessingalgorithm.sip
Expand Up @@ -696,12 +696,26 @@ class QgsProcessingAlgorithm
:rtype: QgsCoordinateReferenceSystem
%End

QgsPointXY parameterAsPoint( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
QgsPointXY parameterAsPoint( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context,
const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() ) const;
%Docstring
Evaluates the parameter with matching ``name`` to a point.

If ``crs`` is set then the point will be automatically
reprojected so that it is in the specified ``crs``.

.. seealso:: parameterAsPointCrs()
:rtype: QgsPointXY
%End

QgsCoordinateReferenceSystem parameterAsPointCrs( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
%Docstring
Returns the coordinate reference system associated with an point parameter value.

.. seealso:: parameterAsPoint()
:rtype: QgsCoordinateReferenceSystem
%End

QString parameterAsFile( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
%Docstring
Evaluates the parameter with matching ``name`` to a file/folder name.
Expand Down
17 changes: 16 additions & 1 deletion python/core/processing/qgsprocessingparameters.sip
Expand Up @@ -570,12 +570,25 @@ class QgsProcessingParameters
:rtype: QgsCoordinateReferenceSystem
%End

static QgsPointXY parameterAsPoint( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
static QgsPointXY parameterAsPoint( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context,
const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
%Docstring
Evaluates the parameter with matching ``definition`` to a point.

If ``crs`` is set then the point will be automatically reprojected so that it is in the specified ``crs``.

.. seealso:: parameterAsPointCrs()
:rtype: QgsPointXY
%End

static QgsCoordinateReferenceSystem parameterAsPointCrs( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Returns the coordinate reference system associated with an point parameter value.

.. seealso:: parameterAsPoint()
:rtype: QgsCoordinateReferenceSystem
%End

static QString parameterAsFile( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``definition`` to a file/folder name.
Expand Down Expand Up @@ -817,6 +830,8 @@ class QgsProcessingParameterPoint : QgsProcessingParameterDefinition
virtual QString type() const;
virtual bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = 0 ) const;

virtual QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const;


static QgsProcessingParameterPoint *fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition ) /Factory/;
%Docstring
Expand Down
3 changes: 2 additions & 1 deletion python/plugins/processing/algs/qgis/ServiceAreaFromLayer.py
Expand Up @@ -35,6 +35,7 @@
QgsUnitTypes,
QgsFeature,
QgsFeatureSink,
QgsFeatureRequest,
QgsGeometry,
QgsFields,
QgsField,
Expand Down Expand Up @@ -208,7 +209,7 @@ def processAlgorithm(self, parameters, context, feedback):
multiplier * 1000.0 / 3600.0)

director.addStrategy(strategy)
builder = QgsGraphBuilder(context.project().crs(),
builder = QgsGraphBuilder(network.sourceCrs(),
True,
tolerance)

Expand Down
4 changes: 2 additions & 2 deletions python/plugins/processing/algs/qgis/ServiceAreaFromPoint.py
Expand Up @@ -163,7 +163,7 @@ def displayName(self):

def processAlgorithm(self, parameters, context, feedback):
network = self.parameterAsSource(parameters, self.INPUT, context)
startPoint = self.parameterAsPoint(parameters, self.START_POINT, context)
startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs())
strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context)

Expand Down Expand Up @@ -200,7 +200,7 @@ def processAlgorithm(self, parameters, context, feedback):
multiplier * 1000.0 / 3600.0)

director.addStrategy(strategy)
builder = QgsGraphBuilder(context.project().crs(),
builder = QgsGraphBuilder(network.sourceCrs(),
True,
tolerance)
feedback.pushInfo(self.tr('Building graph...'))
Expand Down
Expand Up @@ -34,6 +34,7 @@
from qgis.core import (QgsWkbTypes,
QgsUnitTypes,
QgsFeature,
QgsFeatureRequest,
QgsFeatureSink,
QgsGeometry,
QgsFields,
Expand Down Expand Up @@ -158,7 +159,7 @@ def displayName(self):
def processAlgorithm(self, parameters, context, feedback):
network = self.parameterAsSource(parameters, self.INPUT, context)
startPoints = self.parameterAsSource(parameters, self.START_POINTS, context)
endPoint = self.parameterAsPoint(parameters, self.END_POINT, context)
endPoint = self.parameterAsPoint(parameters, self.END_POINT, context, network.sourceCrs())
strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)

directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context)
Expand Down Expand Up @@ -206,7 +207,7 @@ def processAlgorithm(self, parameters, context, feedback):
multiplier = 3600

director.addStrategy(strategy)
builder = QgsGraphBuilder(context.project().crs(),
builder = QgsGraphBuilder(network.sourceCrs(),
True,
tolerance)

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

nPoints = len(snappedPoints)
total = 100.0 / nPoints if nPoints else 1
for i in range(1, count + 1):
for i in range(1, nPoints + 1):
if feedback.isCanceled():
break

Expand Down
Expand Up @@ -36,6 +36,7 @@
QgsFeature,
QgsFeatureSink,
QgsGeometry,
QgsFeatureRequest,
QgsFields,
QgsField,
QgsMessageLog,
Expand Down Expand Up @@ -157,7 +158,7 @@ def displayName(self):

def processAlgorithm(self, parameters, context, feedback):
network = self.parameterAsSource(parameters, self.INPUT, context)
startPoint = self.parameterAsPoint(parameters, self.START_POINT, context)
startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs())
endPoints = self.parameterAsSource(parameters, self.END_POINTS, context)
strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)

Expand Down Expand Up @@ -206,7 +207,7 @@ def processAlgorithm(self, parameters, context, feedback):
multiplier = 3600

director.addStrategy(strategy)
builder = QgsGraphBuilder(context.project().crs(),
builder = QgsGraphBuilder(network.sourceCrs(),
True,
tolerance)

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

nPoints = len(snappedPoints)
total = 100.0 / nPoints if nPoints else 1
for i in range(1, count + 1):
for i in range(1, nPoints + 1):
if feedback.isCanceled():
break

Expand Down
Expand Up @@ -160,8 +160,8 @@ def displayName(self):

def processAlgorithm(self, parameters, context, feedback):
network = self.parameterAsSource(parameters, self.INPUT, context)
startPoint = self.parameterAsPoint(parameters, self.START_POINT, context)
endPoint = self.parameterAsPoint(parameters, self.END_POINT, context)
startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs())
endPoint = self.parameterAsPoint(parameters, self.END_POINT, context, network.sourceCrs())
strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)

directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context)
Expand Down Expand Up @@ -206,7 +206,7 @@ def processAlgorithm(self, parameters, context, feedback):
multiplier = 3600

director.addStrategy(strategy)
builder = QgsGraphBuilder(context.project().crs(),
builder = QgsGraphBuilder(network.sourceCrs(),
True,
tolerance)
feedback.pushInfo(self.tr('Building graph...'))
Expand Down
21 changes: 9 additions & 12 deletions python/plugins/processing/gui/ExtentSelectionPanel.py
Expand Up @@ -79,10 +79,14 @@ def __init__(self, dialog, param):
if param.defaultValue() is not None:
context = createContext()
rect = QgsProcessingParameters.parameterAsExtent(param, {param.name(): param.defaultValue()}, context)
crs = QgsProcessingParameters.parameterAsExtentCrs(param, {param.name(): param.defaultValue()}, context)
if not rect.isNull():
try:
s = '{},{},{},{}'.format(
rect.xMinimum(), rect.xMaximum(), rect.yMinimum(), rect.yMaximum())
if crs.isValid():
s += ' [' + crs.authid() + ']'
self.crs = crs
self.leText.setText(s)
except:
pass
Expand Down Expand Up @@ -133,10 +137,6 @@ def useLayerExtent(self):
self.tr('Use extent from'), extents, False)
if ok:
self.setValueFromRect(QgsReferencedRectangle(extentsDict[item]["extent"], QgsCoordinateReferenceSystem(extentsDict[item]["authid"])))
if extentsDict[item]["authid"] != iface.mapCanvas().mapSettings().destinationCrs().authid():
iface.messageBar().pushMessage(self.tr("Warning"),
self.tr("The projection of the chosen layer is not the same as canvas projection! The selected extent might not be what was intended."),
QgsMessageBar.WARNING, 8)

def selectOnCanvas(self):
canvas = iface.mapCanvas()
Expand All @@ -151,11 +151,14 @@ def setValueFromRect(self, r):
s = '{},{},{},{}'.format(
r.xMinimum(), r.xMaximum(), r.yMinimum(), r.yMaximum())

self.leText.setText(s)
try:
self.crs = r.crs()
except:
self.crs = QgsProject.instance().crs()
if self.crs.isValid():
s += ' [' + self.crs.authid() + ']'

self.leText.setText(s)
self.tool.reset()
canvas = iface.mapCanvas()
canvas.setMapTool(self.prevMapTool)
Expand All @@ -165,13 +168,7 @@ def setValueFromRect(self, r):

def getValue(self):
if str(self.leText.text()).strip() != '':
try:
parts = self.leText.text().split(',')
parts = [float(p) for p in parts]
r = QgsReferencedRectangle(QgsRectangle(parts[0], parts[2], parts[1], parts[3]), self.crs)
return r
except:
return str(self.leText.text())
return str(self.leText.text())
else:
return None

Expand Down
11 changes: 6 additions & 5 deletions python/plugins/processing/gui/PointMapTool.py
Expand Up @@ -25,22 +25,23 @@

__revision__ = '$Format:%H$'

from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtCore import Qt, pyqtSignal

from qgis.gui import QgsMapToolEmitPoint


class PointMapTool(QgsMapToolEmitPoint):

complete = pyqtSignal()

def __init__(self, canvas):
QgsMapToolEmitPoint.__init__(self, canvas)

self.canvas = canvas
self.cursor = Qt.ArrowCursor
self.cursor = Qt.CrossCursor

def activate(self):
self.canvas.setCursor(self.cursor)

def canvasPressEvent(self, event):
pnt = self.toMapCoordinates(event.pos())
self.canvasClicked.emit(pnt, event.button())
def canvasReleaseEvent(self, event):
self.complete.emit()
11 changes: 10 additions & 1 deletion python/plugins/processing/gui/PointSelectionPanel.py
Expand Up @@ -28,6 +28,9 @@

import os

from qgis.core import (QgsProject,
QgsReferencedPointXY,
QgsPointXY)
from qgis.PyQt import uic

from qgis.utils import iface
Expand All @@ -48,13 +51,15 @@ def __init__(self, dialog, default=None):
self.btnSelect.clicked.connect(self.selectOnCanvas)

self.dialog = dialog
self.crs = QgsProject.instance().crs()

if iface is not None:
canvas = iface.mapCanvas()
self.prevMapTool = canvas.mapTool()

self.tool = PointMapTool(canvas)
self.tool.canvasClicked.connect(self.updatePoint)
self.tool.complete.connect(self.pointPicked)
else:
self.prevMapTool = None
self.tool = None
Expand All @@ -76,8 +81,12 @@ def selectOnCanvas(self):

def updatePoint(self, point, button):
s = '{},{}'.format(point.x(), point.y())

self.crs = QgsProject.instance().crs()
if self.crs.isValid():
s += ' [' + self.crs.authid() + ']'
self.leText.setText(s)

def pointPicked(self):
canvas = iface.mapCanvas()
canvas.setMapTool(self.prevMapTool)
self.dialog.showNormal()
Expand Down
9 changes: 7 additions & 2 deletions src/core/processing/qgsprocessingalgorithm.cpp
Expand Up @@ -565,9 +565,14 @@ QgsGeometry QgsProcessingAlgorithm::parameterAsExtentGeometry( const QVariantMap
return QgsProcessingParameters::parameterAsExtentGeometry( parameterDefinition( name ), parameters, context, crs );
}

QgsPointXY QgsProcessingAlgorithm::parameterAsPoint( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
QgsPointXY QgsProcessingAlgorithm::parameterAsPoint( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs ) const
{
return QgsProcessingParameters::parameterAsPoint( parameterDefinition( name ), parameters, context );
return QgsProcessingParameters::parameterAsPoint( parameterDefinition( name ), parameters, context, crs );
}

QgsCoordinateReferenceSystem QgsProcessingAlgorithm::parameterAsPointCrs( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context )
{
return QgsProcessingParameters::parameterAsPointCrs( parameterDefinition( name ), parameters, context );
}

QString QgsProcessingAlgorithm::parameterAsFile( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
Expand Down
15 changes: 14 additions & 1 deletion src/core/processing/qgsprocessingalgorithm.h
Expand Up @@ -680,8 +680,21 @@ class CORE_EXPORT QgsProcessingAlgorithm

/**
* Evaluates the parameter with matching \a name to a point.
*
* If \a crs is set then the point will be automatically
* reprojected so that it is in the specified \a crs.
*
* \see parameterAsPointCrs()
*/
QgsPointXY parameterAsPoint( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context,
const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() ) const;

/**
* Returns the coordinate reference system associated with an point parameter value.
*
* \see parameterAsPoint()
*/
QgsPointXY parameterAsPoint( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
QgsCoordinateReferenceSystem parameterAsPointCrs( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );

/**
* Evaluates the parameter with matching \a name to a file/folder name.
Expand Down

0 comments on commit 14a48c0

Please sign in to comment.