Skip to content
Permalink
Browse files

Port Find Projection alg to new API

Also modify alg to export a vector table of candidates instead of
a HTML list, since a vector table is more useful inside of
models and can be used for further analysis steps.
  • Loading branch information
nyalldawson committed Aug 20, 2017
1 parent a56725f commit cfb926a70de8dcf8a13531c7094427876feef276
@@ -26,31 +26,32 @@
__revision__ = '$Format:%H$'

import os
import codecs

from qgis.core import (QgsApplication,
QgsGeometry,
from qgis.core import (QgsGeometry,
QgsFeature,
QgsFeatureSink,
QgsRectangle,
QgsField,
QgsFields,
QgsCoordinateReferenceSystem,
QgsCoordinateTransform,
QgsProcessingUtils)
QgsWkbTypes,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterExtent,
QgsProcessingParameterCrs,
QgsProcessingParameterFeatureSink)
from qgis.PyQt.QtCore import QVariant

from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterCrs
from processing.core.parameters import ParameterExtent
from processing.core.outputs import OutputHTML

pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]


class FindProjection(QgisAlgorithm):

INPUT_LAYER = 'INPUT_LAYER'
INPUT = 'INPUT'
TARGET_AREA = 'TARGET_AREA'
TARGET_AREA_CRS = 'TARGET_AREA_CRS'
OUTPUT_HTML_FILE = 'OUTPUT_HTML_FILE'
OUTPUT = 'OUTPUT'

def tags(self):
return self.tr('crs,srs,coordinate,reference,system,guess,estimate,finder,determine').split(',')
@@ -62,17 +63,16 @@ def __init__(self):
super().__init__()

def initAlgorithm(self, config=None):
self.addParameter(ParameterVector(self.INPUT_LAYER,
self.tr('Input layer')))
extent_parameter = ParameterExtent(self.TARGET_AREA,
self.tr('Target area for layer'),
self.INPUT_LAYER)
extent_parameter.skip_crs_check = True
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Input layer')))
extent_parameter = QgsProcessingParameterExtent(self.TARGET_AREA,
self.tr('Target area for layer'))
#extent_parameter.skip_crs_check = True
self.addParameter(extent_parameter)
self.addParameter(ParameterCrs(self.TARGET_AREA_CRS, 'Target area CRS'))
self.addParameter(QgsProcessingParameterCrs(self.TARGET_AREA_CRS, 'Target area CRS'))

self.addOutput(OutputHTML(self.OUTPUT_HTML_FILE,
self.tr('Candidates')))
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT,
self.tr('CRS candidates')))

def name(self):
return 'findprojection'
@@ -81,27 +81,34 @@ def displayName(self):
return self.tr('Find projection')

def processAlgorithm(self, parameters, context, feedback):
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
source = self.parameterAsSource(parameters, self.INPUT, context)

extent = self.getParameterValue(self.TARGET_AREA).split(',')
if not extent:
extent = QgsProcessingUtils.combineLayerExtents([layer])
target_crs = QgsCoordinateReferenceSystem(self.getParameterValue(self.TARGET_AREA_CRS))
extent = self.parameterAsExtent(parameters, self.TARGET_AREA, context)
target_crs = self.parameterAsCrs(parameters, self.TARGET_AREA_CRS, context)

target_geom = QgsGeometry.fromRect(QgsRectangle(float(extent[0]), float(extent[2]),
float(extent[1]), float(extent[3])))
target_geom = QgsGeometry.fromRect(extent)

output_file = self.getOutputValue(self.OUTPUT_HTML_FILE)
fields = QgsFields()
fields.append(QgsField('auth_id', QVariant.String, '', 20))

(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem())

# make intersection tests nice and fast
engine = QgsGeometry.createGeometryEngine(target_geom.geometry())
engine.prepareGeometry()

layer_bounds = QgsGeometry.fromRect(layer.extent())
layer_bounds = QgsGeometry.fromRect(source.sourceExtent())

crses_to_check = QgsCoordinateReferenceSystem.validSrsIds()
total = 100.0 / len(crses_to_check)

found_results = 0

results = []
for current, srs_id in enumerate(crses_to_check):
if feedback.isCanceled():
break

for srs_id in QgsCoordinateReferenceSystem.validSrsIds():
candidate_crs = QgsCoordinateReferenceSystem.fromSrsId(srs_id)
if not candidate_crs.isValid():
continue
@@ -115,15 +122,15 @@ def processAlgorithm(self, parameters, context, feedback):
continue

if engine.intersects(transformed_bounds.geometry()):
results.append(candidate_crs.authid())

self.createHTML(output_file, results)

def createHTML(self, outputFile, candidates):
with codecs.open(outputFile, 'w', encoding='utf-8') as f:
f.write('<html><head>\n')
f.write('<meta http-equiv="Content-Type" content="text/html; \
charset=utf-8" /></head><body>\n')
for c in candidates:
f.write('<p>' + c + '</p>\n')
f.write('</body></html>\n')
feedback.pushInfo(self.tr('Found candidate CRS: {}').format(candidate_crs.authid()))
f = QgsFeature(fields)
f.setAttributes([candidate_crs.authid()])
sink.addFeature(f, QgsFeatureSink.FastInsert)
found_results += 1

feedback.setProgress(int(current * total))

if found_results == 0:
feedback.reportError(self.tr('No matching projections found'))

return {self.OUTPUT: dest_id}
@@ -73,6 +73,7 @@
from .FieldPyculator import FieldsPyculator
from .FieldsCalculator import FieldsCalculator
from .FieldsMapper import FieldsMapper
from .FindProjection import FindProjection
from .FixedDistanceBuffer import FixedDistanceBuffer
from .FixGeometry import FixGeometry
from .GeometryByExpression import GeometryByExpression
@@ -172,7 +173,6 @@
# from .DefineProjection import DefineProjection
# from .RasterCalculator import RasterCalculator
# from .ExecuteSQL import ExecuteSQL
# from .FindProjection import FindProjection

pluginPath = os.path.normpath(os.path.join(
os.path.split(os.path.dirname(__file__))[0], os.pardir))
@@ -194,7 +194,7 @@ def getAlgs(self):
# SelectByAttributeSum()
# DefineProjection(),
# RasterCalculator(),
# ExecuteSQL(), FindProjection(),
# ExecuteSQL(),
# ]
algs = [AddTableField(),
Aggregate(),
@@ -229,6 +229,7 @@ def getAlgs(self):
FieldsCalculator(),
FieldsMapper(),
FieldsPyculator(),
FindProjection(),
FixedDistanceBuffer(),
FixGeometry(),
GeometryByExpression(),
@@ -0,0 +1,16 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>projection_candidates</Name>
<ElementPath>projection_candidates</ElementPath>
<GeometryType>100</GeometryType>
<DatasetSpecificInfo>
<FeatureCount>8</FeatureCount>
</DatasetSpecificInfo>
<PropertyDefn>
<Name>auth_id</Name>
<ElementPath>auth_id</ElementPath>
<Type>String</Type>
<Width>14</Width>
</PropertyDefn>
</GMLFeatureClass>
</GMLFeatureClassList>
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy><gml:null>missing</gml:null></gml:boundedBy>

<gml:featureMember>
<ogr:projection_candidates fid="projection_candidates.0">
<ogr:auth_id>EPSG:20256</ogr:auth_id>
</ogr:projection_candidates>
</gml:featureMember>
<gml:featureMember>
<ogr:projection_candidates fid="projection_candidates.1">
<ogr:auth_id>EPSG:20356</ogr:auth_id>
</ogr:projection_candidates>
</gml:featureMember>
<gml:featureMember>
<ogr:projection_candidates fid="projection_candidates.2">
<ogr:auth_id>EPSG:28356</ogr:auth_id>
</ogr:projection_candidates>
</gml:featureMember>
<gml:featureMember>
<ogr:projection_candidates fid="projection_candidates.3">
<ogr:auth_id>EPSG:32356</ogr:auth_id>
</ogr:projection_candidates>
</gml:featureMember>
<gml:featureMember>
<ogr:projection_candidates fid="projection_candidates.4">
<ogr:auth_id>EPSG:32556</ogr:auth_id>
</ogr:projection_candidates>
</gml:featureMember>
<gml:featureMember>
<ogr:projection_candidates fid="projection_candidates.5">
<ogr:auth_id>EPSG:32756</ogr:auth_id>
</ogr:projection_candidates>
</gml:featureMember>
<gml:featureMember>
<ogr:projection_candidates fid="projection_candidates.6">
<ogr:auth_id>IGNF:UTM56SW84</ogr:auth_id>
</ogr:projection_candidates>
</gml:featureMember>
<gml:featureMember>
<ogr:projection_candidates fid="projection_candidates.7">
<ogr:auth_id>EPSG:5552</ogr:auth_id>
</ogr:projection_candidates>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -2827,19 +2827,19 @@ tests:
fields:
fid: skip

# - algorithm: qgis:findprojection
# name: Find projection
# params:
# INPUT_LAYER:
# name: custom/find_projection.gml
# type: vector
# TARGET_AREA: 151.1198,151.1368,-33.9118,-33.9003
# TARGET_AREA_CRS: EPSG:4326
# results:
# OUTPUT_HTML_FILE:
# name: expected/find_projection.html
# type: file
#
- algorithm: qgis:findprojection
name: Find projection
params:
INPUT:
name: custom/find_projection.gml
type: vector
TARGET_AREA: 151.1198,151.1368,-33.9118,-33.9003
TARGET_AREA_CRS: EPSG:4326
results:
OUTPUT:
name: expected/projection_candidates.gml
type: vector

- algorithm: qgis:polygonfromlayerextent
name: Standard polygon from layer extent
params:

0 comments on commit cfb926a

Please sign in to comment.
You can’t perform that action at this time.