mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-08 00:05:09 -04:00
[feature] Add support for georeferencing vector layers in georeferencer
Allows vector layers without spatial referencing to be interactively georeferenced (or layers with referencing to be re-referenced!) Sponsored by the Danish QGIS Usergroup
This commit is contained in:
parent
ebf9fe1809
commit
d4eb6f524f
@ -2,6 +2,6 @@
|
|||||||
# monkey patching scoped based enum
|
# monkey patching scoped based enum
|
||||||
QgsVectorWarperTask.Result.Success.__doc__ = "Warping completed successfully"
|
QgsVectorWarperTask.Result.Success.__doc__ = "Warping completed successfully"
|
||||||
QgsVectorWarperTask.Result.Canceled.__doc__ = "Task was canceled before completion"
|
QgsVectorWarperTask.Result.Canceled.__doc__ = "Task was canceled before completion"
|
||||||
QgsVectorWarperTask.Result.Error.__doc__ = ""
|
QgsVectorWarperTask.Result.Error.__doc__ = "An error occurred while warping"
|
||||||
QgsVectorWarperTask.Result.__doc__ = 'Task results\n\n' + '* ``Success``: ' + QgsVectorWarperTask.Result.Success.__doc__ + '\n' + '* ``Canceled``: ' + QgsVectorWarperTask.Result.Canceled.__doc__ + '\n' + '* ``Error``: ' + QgsVectorWarperTask.Result.Error.__doc__
|
QgsVectorWarperTask.Result.__doc__ = 'Task results\n\n' + '* ``Success``: ' + QgsVectorWarperTask.Result.Success.__doc__ + '\n' + '* ``Canceled``: ' + QgsVectorWarperTask.Result.Canceled.__doc__ + '\n' + '* ``Error``: ' + QgsVectorWarperTask.Result.Error.__doc__
|
||||||
# --
|
# --
|
||||||
|
@ -68,6 +68,15 @@ A task for warping a vector layer in a background thread.
|
|||||||
const QgsCoordinateReferenceSystem &destinationCrs,
|
const QgsCoordinateReferenceSystem &destinationCrs,
|
||||||
QgsVectorLayer *layer,
|
QgsVectorLayer *layer,
|
||||||
const QString &fileName );
|
const QString &fileName );
|
||||||
|
%Docstring
|
||||||
|
Constructor for QgsVectorWarperTask.
|
||||||
|
|
||||||
|
:param method: transformation method
|
||||||
|
:param points: GCP point list
|
||||||
|
:param destinationCrs: destination layer CRS
|
||||||
|
:param layer: source layer
|
||||||
|
:param fileName: filename for destination layer
|
||||||
|
%End
|
||||||
|
|
||||||
virtual void cancel();
|
virtual void cancel();
|
||||||
|
|
||||||
@ -76,7 +85,7 @@ A task for warping a vector layer in a background thread.
|
|||||||
{
|
{
|
||||||
Success,
|
Success,
|
||||||
Canceled,
|
Canceled,
|
||||||
Error
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
Result result() const;
|
Result result() const;
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
qgsgcptransformer.cpp
|
qgsgcptransformer.cpp
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
Date : February 2022
|
Date : February 2022
|
||||||
Copyright : (C) 2022 by Alex (roya0045)
|
Copyright : (C) 2022 by Nyall Dawson
|
||||||
Email :
|
Email : nyall dot dawson at gmail dot com
|
||||||
***************************************************************************
|
***************************************************************************
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
qgsvectorwarper.h
|
qgsvectorwarper.h
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
Date : February 2022
|
Date : February 2022
|
||||||
Copyright : (C) 2022 by Alex (roya0045)
|
Copyright : (C) 2022 by Nyall Dawson
|
||||||
Email :
|
Email : nyall dot dawson at gmail dot com
|
||||||
***************************************************************************
|
***************************************************************************
|
||||||
* *
|
* *
|
||||||
* This program is free software; you can redistribute it and/or modify *
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
@ -88,6 +88,15 @@ class ANALYSIS_EXPORT QgsVectorWarperTask : public QgsTask
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for QgsVectorWarperTask.
|
||||||
|
*
|
||||||
|
* \param method transformation method
|
||||||
|
* \param points GCP point list
|
||||||
|
* \param destinationCrs destination layer CRS
|
||||||
|
* \param layer source layer
|
||||||
|
* \param fileName filename for destination layer
|
||||||
|
*/
|
||||||
QgsVectorWarperTask( QgsGcpTransformerInterface::TransformMethod method, const QList < QgsGcpPoint > &points,
|
QgsVectorWarperTask( QgsGcpTransformerInterface::TransformMethod method, const QList < QgsGcpPoint > &points,
|
||||||
const QgsCoordinateReferenceSystem &destinationCrs,
|
const QgsCoordinateReferenceSystem &destinationCrs,
|
||||||
QgsVectorLayer *layer,
|
QgsVectorLayer *layer,
|
||||||
@ -100,7 +109,7 @@ class ANALYSIS_EXPORT QgsVectorWarperTask : public QgsTask
|
|||||||
{
|
{
|
||||||
Success, //!< Warping completed successfully
|
Success, //!< Warping completed successfully
|
||||||
Canceled, //!< Task was canceled before completion
|
Canceled, //!< Task was canceled before completion
|
||||||
Error
|
Error, //!< An error occurred while warping
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -359,6 +359,7 @@ ADD_PYTHON_TEST(PyQgsVectorLayerSelectedFeatureSource test_qgsvectorlayerselecte
|
|||||||
ADD_PYTHON_TEST(PyQgsVectorLayerShapefile test_qgsvectorlayershapefile.py)
|
ADD_PYTHON_TEST(PyQgsVectorLayerShapefile test_qgsvectorlayershapefile.py)
|
||||||
ADD_PYTHON_TEST(PyQgsVectorLayerTemporalProperties test_qgsvectorlayertemporalproperties.py)
|
ADD_PYTHON_TEST(PyQgsVectorLayerTemporalProperties test_qgsvectorlayertemporalproperties.py)
|
||||||
ADD_PYTHON_TEST(PyQgsVectorLayerUtils test_qgsvectorlayerutils.py)
|
ADD_PYTHON_TEST(PyQgsVectorLayerUtils test_qgsvectorlayerutils.py)
|
||||||
|
ADD_PYTHON_TEST(PyQgsVectorWarper test_qgsvectorwarper.py)
|
||||||
ADD_PYTHON_TEST(PyQgsZonalStatistics test_qgszonalstatistics.py)
|
ADD_PYTHON_TEST(PyQgsZonalStatistics test_qgszonalstatistics.py)
|
||||||
ADD_PYTHON_TEST(PyQgsVirtualLayerProvider test_provider_virtual.py)
|
ADD_PYTHON_TEST(PyQgsVirtualLayerProvider test_provider_virtual.py)
|
||||||
ADD_PYTHON_TEST(PyQgsVirtualLayerTask test_qgsvirtuallayertask.py)
|
ADD_PYTHON_TEST(PyQgsVirtualLayerTask test_qgsvirtuallayertask.py)
|
||||||
|
88
tests/src/python/test_qgsvectorwarper.py
Normal file
88
tests/src/python/test_qgsvectorwarper.py
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""QGIS Unit tests for QgsVectorWarper
|
||||||
|
|
||||||
|
.. note:: This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
"""
|
||||||
|
__author__ = 'Nyall Dawson'
|
||||||
|
__date__ = '01/03/2022'
|
||||||
|
__copyright__ = 'Copyright 2022, The QGIS Project'
|
||||||
|
|
||||||
|
import qgis # NOQA
|
||||||
|
from qgis.analysis import (
|
||||||
|
QgsVectorWarper,
|
||||||
|
QgsGcpPoint,
|
||||||
|
QgsGcpTransformerInterface
|
||||||
|
)
|
||||||
|
from qgis.core import (
|
||||||
|
QgsVectorLayer,
|
||||||
|
QgsFeature,
|
||||||
|
QgsGeometry,
|
||||||
|
QgsPointXY,
|
||||||
|
QgsFeatureStore,
|
||||||
|
QgsCoordinateReferenceSystem,
|
||||||
|
QgsProject
|
||||||
|
)
|
||||||
|
from qgis.testing import start_app, unittest
|
||||||
|
|
||||||
|
start_app()
|
||||||
|
|
||||||
|
|
||||||
|
class TestQgsVectorWarper(unittest.TestCase):
|
||||||
|
|
||||||
|
def testWarper(self):
|
||||||
|
# create source layer
|
||||||
|
source_layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
|
||||||
|
"addfeat", "memory")
|
||||||
|
pr = source_layer.dataProvider()
|
||||||
|
f = QgsFeature()
|
||||||
|
f.setAttributes(["test", 123])
|
||||||
|
f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
|
||||||
|
f2 = QgsFeature()
|
||||||
|
f2.setAttributes(["test2", 457])
|
||||||
|
f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(200, 200)))
|
||||||
|
f3 = QgsFeature()
|
||||||
|
f3.setAttributes(["test3", 888])
|
||||||
|
f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(300, 200)))
|
||||||
|
f4 = QgsFeature()
|
||||||
|
f4.setAttributes(["test4", -1])
|
||||||
|
f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(400, 300)))
|
||||||
|
f5 = QgsFeature()
|
||||||
|
f5.setAttributes(["test5", 0])
|
||||||
|
f5.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(0, 0)))
|
||||||
|
self.assertTrue(pr.addFeatures([f, f2, f3, f4, f5]))
|
||||||
|
self.assertTrue(source_layer.featureCount() == 5)
|
||||||
|
|
||||||
|
# create sink
|
||||||
|
sink = QgsFeatureStore()
|
||||||
|
warper = QgsVectorWarper(QgsGcpTransformerInterface.TransformMethod.PolynomialOrder1,
|
||||||
|
[
|
||||||
|
QgsGcpPoint(QgsPointXY(90, 210), QgsPointXY(8, 20),
|
||||||
|
QgsCoordinateReferenceSystem('EPSG:4283'), True),
|
||||||
|
QgsGcpPoint(QgsPointXY(210, 190), QgsPointXY(20.5, 20),
|
||||||
|
QgsCoordinateReferenceSystem('EPSG:4283'), True),
|
||||||
|
QgsGcpPoint(QgsPointXY(350, 220), QgsPointXY(30, 21),
|
||||||
|
QgsCoordinateReferenceSystem('EPSG:4283'), True),
|
||||||
|
QgsGcpPoint(QgsPointXY(390, 290), QgsPointXY(39, 28),
|
||||||
|
QgsCoordinateReferenceSystem('EPSG:4283'), True),
|
||||||
|
],
|
||||||
|
QgsCoordinateReferenceSystem('EPSG:4283'))
|
||||||
|
|
||||||
|
self.assertTrue(warper.transformFeatures(source_layer.getFeatures(),
|
||||||
|
sink,
|
||||||
|
QgsProject.instance().transformContext()))
|
||||||
|
|
||||||
|
self.assertEqual(sink.count(), 5)
|
||||||
|
feature_map = {f.attributes()[0]: {'geom': f.geometry().asWkt(1),
|
||||||
|
'attributes': f.attributes()} for f in sink.features()}
|
||||||
|
self.assertEqual(feature_map, {'test': {'geom': 'Point (9.4 19.7)', 'attributes': ['test', 123]},
|
||||||
|
'test2': {'geom': 'Point (18 19.9)', 'attributes': ['test2', 457]},
|
||||||
|
'test3': {'geom': 'Point (26.6 20.1)', 'attributes': ['test3', 888]},
|
||||||
|
'test4': {'geom': 'Point (39.6 28.5)', 'attributes': ['test4', -1]},
|
||||||
|
'test5': {'geom': 'Point (-7.8 3)', 'attributes': ['test5', 0]}})
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user