mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-08 00:05:09 -04:00
Merge pull request #62539 from nyalldawson/package_dest_crs
Add optional destination crs for Package Layers algorithm
This commit is contained in:
commit
d22e0d2eb2
@ -49,7 +49,7 @@ try:
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
QgsVectorFileWriter.SaveVectorOptions.__attribute_docs__ = {'driverName': 'OGR driver to use', 'layerName': 'Layer name. If let empty, it will be derived from the filename', 'actionOnExistingFile': 'Action on existing file', 'fileEncoding': 'Encoding to use', 'ct': 'Transform to reproject exported geometries with, or invalid transform\nfor no transformation', 'onlySelectedFeatures': 'Write only selected features of layer', 'datasourceOptions': 'List of OGR data source creation options', 'layerOptions': 'List of OGR layer creation options', 'skipAttributeCreation': 'Only write geometries', 'attributes': 'Attributes to export (empty means all unless skipAttributeCreation is set)', 'attributesExportNames': 'Attributes export names', 'symbologyExport': 'Symbology to export', 'symbologyScale': 'Scale of symbology', 'filterExtent': 'If not empty, only features intersecting the extent will be saved', 'overrideGeometryType': 'Set to a valid geometry type to override the default geometry type for the layer. This parameter\nallows for conversion of geometryless tables to null geometries, etc.', 'forceMulti': 'Sets to ``True`` to force creation of multipart geometries', 'includeZ': 'Sets to ``True`` to include z dimension in output. This option is only valid if overrideGeometryType is set', 'fieldValueConverter': 'Field value converter.\n\nOwnership is not transferred and callers must ensure that the lifetime of fieldValueConverter\nexceeds the lifetime of the :py:class:`QgsVectorFileWriter` object.', 'feedback': 'Optional feedback object allowing cancellation of layer save', 'fieldNameSource': 'Source for exported field names.\n\n.. versionadded:: 3.18', 'saveMetadata': 'Set to ``True`` to save layer metadata for the exported vector file.\n\n.. seealso:: :py:func:`layerMetadata`\n\n.. versionadded:: 3.20', 'layerMetadata': 'Layer metadata to save for the exported vector file. This will only be used if saveMetadata is ``True``.\n\n.. seealso:: :py:func:`saveMetadata`\n\n.. versionadded:: 3.20', 'includeConstraints': 'Set to ``True`` to transfer field constraints to the exported vector file.\n\nSupport for field constraints depends on the output file format.\n\n.. versionadded:: 3.34', 'setFieldDomains': 'Set to ``True`` to transfer field domains to the exported vector file.\n\nSupport for field domains depends on the output file format.\n\n.. note::\n\n Only available in builds based on GDAL 3.5 or later\n\n.. versionadded:: 3.36', 'sourceDatabaseProviderConnection': 'Source database provider connection, for field domains.\n\nOwnership is not transferred and callers must ensure that the lifetime of sourceDatabaseProviderConnection\nexceeds the lifetime of the :py:class:`QgsVectorFileWriter` object.\n\n.. versionadded:: 3.36'}
|
||||
QgsVectorFileWriter.SaveVectorOptions.__attribute_docs__ = {'driverName': 'OGR driver to use', 'layerName': 'Layer name. If let empty, it will be derived from the filename', 'actionOnExistingFile': 'Action on existing file', 'fileEncoding': 'Encoding to use', 'ct': 'Transform to reproject exported geometries with, or invalid transform\nfor no transformation', 'onlySelectedFeatures': 'Write only selected features of layer', 'datasourceOptions': 'List of OGR data source creation options', 'layerOptions': 'List of OGR layer creation options', 'skipAttributeCreation': 'Only write geometries', 'attributes': 'Attributes to export (empty means all unless skipAttributeCreation is set)', 'attributesExportNames': 'Attributes export names', 'symbologyExport': 'Symbology to export', 'symbologyScale': 'Scale of symbology', 'filterExtent': "If not empty, only features intersecting the extent will be saved.\n\nThe filter extent should be in the destination CRS (if transforming), or the layer's\nCRS if no valid transform is set.", 'overrideGeometryType': 'Set to a valid geometry type to override the default geometry type for the layer. This parameter\nallows for conversion of geometryless tables to null geometries, etc.', 'forceMulti': 'Sets to ``True`` to force creation of multipart geometries', 'includeZ': 'Sets to ``True`` to include z dimension in output. This option is only valid if overrideGeometryType is set', 'fieldValueConverter': 'Field value converter.\n\nOwnership is not transferred and callers must ensure that the lifetime of fieldValueConverter\nexceeds the lifetime of the :py:class:`QgsVectorFileWriter` object.', 'feedback': 'Optional feedback object allowing cancellation of layer save', 'fieldNameSource': 'Source for exported field names.\n\n.. versionadded:: 3.18', 'saveMetadata': 'Set to ``True`` to save layer metadata for the exported vector file.\n\n.. seealso:: :py:func:`layerMetadata`\n\n.. versionadded:: 3.20', 'layerMetadata': 'Layer metadata to save for the exported vector file. This will only be used if saveMetadata is ``True``.\n\n.. seealso:: :py:func:`saveMetadata`\n\n.. versionadded:: 3.20', 'includeConstraints': 'Set to ``True`` to transfer field constraints to the exported vector file.\n\nSupport for field constraints depends on the output file format.\n\n.. versionadded:: 3.34', 'setFieldDomains': 'Set to ``True`` to transfer field domains to the exported vector file.\n\nSupport for field domains depends on the output file format.\n\n.. note::\n\n Only available in builds based on GDAL 3.5 or later\n\n.. versionadded:: 3.36', 'sourceDatabaseProviderConnection': 'Source database provider connection, for field domains.\n\nOwnership is not transferred and callers must ensure that the lifetime of sourceDatabaseProviderConnection\nexceeds the lifetime of the :py:class:`QgsVectorFileWriter` object.\n\n.. versionadded:: 3.36'}
|
||||
QgsVectorFileWriter.SaveVectorOptions.__annotations__ = {'driverName': str, 'layerName': str, 'actionOnExistingFile': 'QgsVectorFileWriter.ActionOnExistingFile', 'fileEncoding': str, 'ct': 'QgsCoordinateTransform', 'onlySelectedFeatures': bool, 'datasourceOptions': 'List[str]', 'layerOptions': 'List[str]', 'skipAttributeCreation': bool, 'attributes': 'QgsAttributeList', 'attributesExportNames': 'List[str]', 'symbologyExport': 'Qgis.FeatureSymbologyExport', 'symbologyScale': float, 'filterExtent': 'QgsRectangle', 'overrideGeometryType': 'Qgis.WkbType', 'forceMulti': bool, 'includeZ': bool, 'fieldValueConverter': 'QgsVectorFileWriter.FieldValueConverter', 'feedback': 'QgsFeedback', 'fieldNameSource': 'QgsVectorFileWriter.FieldNameSource', 'saveMetadata': bool, 'layerMetadata': 'QgsLayerMetadata', 'includeConstraints': bool, 'setFieldDomains': bool, 'sourceDatabaseProviderConnection': 'QgsAbstractDatabaseProviderConnection'}
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
|
@ -5,7 +5,7 @@ try:
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
try:
|
||||
QgsVectorFileWriter.SaveVectorOptions.__attribute_docs__ = {'driverName': 'OGR driver to use', 'layerName': 'Layer name. If let empty, it will be derived from the filename', 'actionOnExistingFile': 'Action on existing file', 'fileEncoding': 'Encoding to use', 'ct': 'Transform to reproject exported geometries with, or invalid transform\nfor no transformation', 'onlySelectedFeatures': 'Write only selected features of layer', 'datasourceOptions': 'List of OGR data source creation options', 'layerOptions': 'List of OGR layer creation options', 'skipAttributeCreation': 'Only write geometries', 'attributes': 'Attributes to export (empty means all unless skipAttributeCreation is set)', 'attributesExportNames': 'Attributes export names', 'symbologyExport': 'Symbology to export', 'symbologyScale': 'Scale of symbology', 'filterExtent': 'If not empty, only features intersecting the extent will be saved', 'overrideGeometryType': 'Set to a valid geometry type to override the default geometry type for the layer. This parameter\nallows for conversion of geometryless tables to null geometries, etc.', 'forceMulti': 'Sets to ``True`` to force creation of multipart geometries', 'includeZ': 'Sets to ``True`` to include z dimension in output. This option is only valid if overrideGeometryType is set', 'fieldValueConverter': 'Field value converter.\n\nOwnership is not transferred and callers must ensure that the lifetime of fieldValueConverter\nexceeds the lifetime of the :py:class:`QgsVectorFileWriter` object.', 'feedback': 'Optional feedback object allowing cancellation of layer save', 'fieldNameSource': 'Source for exported field names.\n\n.. versionadded:: 3.18', 'saveMetadata': 'Set to ``True`` to save layer metadata for the exported vector file.\n\n.. seealso:: :py:func:`layerMetadata`\n\n.. versionadded:: 3.20', 'layerMetadata': 'Layer metadata to save for the exported vector file. This will only be used if saveMetadata is ``True``.\n\n.. seealso:: :py:func:`saveMetadata`\n\n.. versionadded:: 3.20', 'includeConstraints': 'Set to ``True`` to transfer field constraints to the exported vector file.\n\nSupport for field constraints depends on the output file format.\n\n.. versionadded:: 3.34', 'setFieldDomains': 'Set to ``True`` to transfer field domains to the exported vector file.\n\nSupport for field domains depends on the output file format.\n\n.. note::\n\n Only available in builds based on GDAL 3.5 or later\n\n.. versionadded:: 3.36', 'sourceDatabaseProviderConnection': 'Source database provider connection, for field domains.\n\nOwnership is not transferred and callers must ensure that the lifetime of sourceDatabaseProviderConnection\nexceeds the lifetime of the :py:class:`QgsVectorFileWriter` object.\n\n.. versionadded:: 3.36'}
|
||||
QgsVectorFileWriter.SaveVectorOptions.__attribute_docs__ = {'driverName': 'OGR driver to use', 'layerName': 'Layer name. If let empty, it will be derived from the filename', 'actionOnExistingFile': 'Action on existing file', 'fileEncoding': 'Encoding to use', 'ct': 'Transform to reproject exported geometries with, or invalid transform\nfor no transformation', 'onlySelectedFeatures': 'Write only selected features of layer', 'datasourceOptions': 'List of OGR data source creation options', 'layerOptions': 'List of OGR layer creation options', 'skipAttributeCreation': 'Only write geometries', 'attributes': 'Attributes to export (empty means all unless skipAttributeCreation is set)', 'attributesExportNames': 'Attributes export names', 'symbologyExport': 'Symbology to export', 'symbologyScale': 'Scale of symbology', 'filterExtent': "If not empty, only features intersecting the extent will be saved.\n\nThe filter extent should be in the destination CRS (if transforming), or the layer's\nCRS if no valid transform is set.", 'overrideGeometryType': 'Set to a valid geometry type to override the default geometry type for the layer. This parameter\nallows for conversion of geometryless tables to null geometries, etc.', 'forceMulti': 'Sets to ``True`` to force creation of multipart geometries', 'includeZ': 'Sets to ``True`` to include z dimension in output. This option is only valid if overrideGeometryType is set', 'fieldValueConverter': 'Field value converter.\n\nOwnership is not transferred and callers must ensure that the lifetime of fieldValueConverter\nexceeds the lifetime of the :py:class:`QgsVectorFileWriter` object.', 'feedback': 'Optional feedback object allowing cancellation of layer save', 'fieldNameSource': 'Source for exported field names.\n\n.. versionadded:: 3.18', 'saveMetadata': 'Set to ``True`` to save layer metadata for the exported vector file.\n\n.. seealso:: :py:func:`layerMetadata`\n\n.. versionadded:: 3.20', 'layerMetadata': 'Layer metadata to save for the exported vector file. This will only be used if saveMetadata is ``True``.\n\n.. seealso:: :py:func:`saveMetadata`\n\n.. versionadded:: 3.20', 'includeConstraints': 'Set to ``True`` to transfer field constraints to the exported vector file.\n\nSupport for field constraints depends on the output file format.\n\n.. versionadded:: 3.34', 'setFieldDomains': 'Set to ``True`` to transfer field domains to the exported vector file.\n\nSupport for field domains depends on the output file format.\n\n.. note::\n\n Only available in builds based on GDAL 3.5 or later\n\n.. versionadded:: 3.36', 'sourceDatabaseProviderConnection': 'Source database provider connection, for field domains.\n\nOwnership is not transferred and callers must ensure that the lifetime of sourceDatabaseProviderConnection\nexceeds the lifetime of the :py:class:`QgsVectorFileWriter` object.\n\n.. versionadded:: 3.36'}
|
||||
QgsVectorFileWriter.SaveVectorOptions.__annotations__ = {'driverName': str, 'layerName': str, 'actionOnExistingFile': 'QgsVectorFileWriter.ActionOnExistingFile', 'fileEncoding': str, 'ct': 'QgsCoordinateTransform', 'onlySelectedFeatures': bool, 'datasourceOptions': 'List[str]', 'layerOptions': 'List[str]', 'skipAttributeCreation': bool, 'attributes': 'QgsAttributeList', 'attributesExportNames': 'List[str]', 'symbologyExport': 'Qgis.FeatureSymbologyExport', 'symbologyScale': float, 'filterExtent': 'QgsRectangle', 'overrideGeometryType': 'Qgis.WkbType', 'forceMulti': bool, 'includeZ': bool, 'fieldValueConverter': 'QgsVectorFileWriter.FieldValueConverter', 'feedback': 'QgsFeedback', 'fieldNameSource': 'QgsVectorFileWriter.FieldNameSource', 'saveMetadata': bool, 'layerMetadata': 'QgsLayerMetadata', 'includeConstraints': bool, 'setFieldDomains': bool, 'sourceDatabaseProviderConnection': 'QgsAbstractDatabaseProviderConnection'}
|
||||
except (NameError, AttributeError):
|
||||
pass
|
||||
|
@ -64,6 +64,12 @@ void QgsPackageAlgorithm::initAlgorithm( const QVariantMap & )
|
||||
auto extentParam = std::make_unique<QgsProcessingParameterExtent>( QStringLiteral( "EXTENT" ), QObject::tr( "Extent" ), QVariant(), true );
|
||||
extentParam->setHelp( QObject::tr( "Limit exported features to those with geometries intersecting the provided extent" ) );
|
||||
addParameter( extentParam.release() );
|
||||
|
||||
auto crsParam = std::make_unique< QgsProcessingParameterCrs >( QStringLiteral( "CRS" ), QObject::tr( "Destination CRS" ), QVariant(), true );
|
||||
crsParam->setFlags( crsParam->flags() | Qgis::ProcessingParameterFlag::Advanced );
|
||||
crsParam->setHelp( QObject::tr( "If set, all layers will be transformed to the destination CRS during packaging." ) );
|
||||
addParameter( std::move( crsParam ) );
|
||||
|
||||
addOutput( new QgsProcessingOutputMultipleLayers( QStringLiteral( "OUTPUT_LAYERS" ), QObject::tr( "Layers within new package" ) ) );
|
||||
}
|
||||
|
||||
@ -98,6 +104,8 @@ bool QgsPackageAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsPr
|
||||
feedback->reportError( QObject::tr( "No layers selected, geopackage will be empty" ), false );
|
||||
}
|
||||
|
||||
mDestinationCrs = parameterAsCrs( parameters, QStringLiteral( "CRS" ), context );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -354,7 +362,7 @@ QVariantMap QgsPackageAlgorithm::processAlgorithm( const QVariantMap ¶meters
|
||||
feedback->pushWarning( QObject::tr( "No spatial index exists for layer %1, performance will be severely degraded" ).arg( vectorLayer->name() ) );
|
||||
}
|
||||
|
||||
extent = parameterAsExtent( parameters, QStringLiteral( "EXTENT" ), context, layer->crs() );
|
||||
extent = parameterAsExtent( parameters, QStringLiteral( "EXTENT" ), context, mDestinationCrs.isValid() ? mDestinationCrs : layer->crs() );
|
||||
}
|
||||
|
||||
if ( !packageVectorLayer( vectorLayer, packagePath, context, &multiStepFeedback, saveStyles, saveMetadata, selectedFeaturesOnly, extent ) )
|
||||
@ -440,6 +448,11 @@ bool QgsPackageAlgorithm::packageVectorLayer( QgsVectorLayer *layer, const QStri
|
||||
options.saveMetadata = true;
|
||||
}
|
||||
|
||||
if ( mDestinationCrs.isValid() )
|
||||
{
|
||||
options.ct = QgsCoordinateTransform( layer->crs(), mDestinationCrs, context.transformContext() );
|
||||
}
|
||||
|
||||
// Check FID compatibility with GPKG and remove any existing FID field if not compatible,
|
||||
// let this be completely recreated since many layer sources have fid fields which are
|
||||
// not compatible with gpkg requirements
|
||||
|
@ -53,6 +53,7 @@ class QgsPackageAlgorithm : public QgsProcessingAlgorithm
|
||||
|
||||
std::vector<std::unique_ptr<QgsMapLayer>> mLayers;
|
||||
QMap<QString, QString> mClonedLayerIds;
|
||||
QgsCoordinateReferenceSystem mDestinationCrs;
|
||||
};
|
||||
|
||||
///@endcond PRIVATE
|
||||
|
@ -501,7 +501,12 @@ class CORE_EXPORT QgsVectorFileWriter : public QgsFeatureSink
|
||||
//! Scale of symbology
|
||||
double symbologyScale = 1.0;
|
||||
|
||||
//! If not empty, only features intersecting the extent will be saved
|
||||
/**
|
||||
* If not empty, only features intersecting the extent will be saved.
|
||||
*
|
||||
* The filter extent should be in the destination CRS (if transforming), or the layer's
|
||||
* CRS if no valid transform is set.
|
||||
*/
|
||||
QgsRectangle filterExtent;
|
||||
|
||||
/**
|
||||
|
@ -25,6 +25,9 @@ from qgis.core import (
|
||||
QgsRelation,
|
||||
QgsSettings,
|
||||
QgsVectorLayer,
|
||||
QgsReferencedRectangle,
|
||||
QgsCoordinateReferenceSystem,
|
||||
QgsRectangle,
|
||||
)
|
||||
import unittest
|
||||
from qgis.testing import start_app, QgisTestCase
|
||||
@ -110,11 +113,11 @@ class TestPackageLayers(QgisTestCase):
|
||||
f = ogr.Feature(lyr.GetLayerDefn())
|
||||
f["name"] = "region one"
|
||||
outring = ogr.Geometry(ogr.wkbLinearRing)
|
||||
outring.AddPoint(2580000, 1220500)
|
||||
outring.AddPoint(2581000, 1220500)
|
||||
outring.AddPoint(2581000, 1221500)
|
||||
outring.AddPoint(2580000, 1221500)
|
||||
outring.AddPoint(2580000, 1220500)
|
||||
outring.AddPoint_2D(2580000, 1220500)
|
||||
outring.AddPoint_2D(2581000, 1220500)
|
||||
outring.AddPoint_2D(2581000, 1221500)
|
||||
outring.AddPoint_2D(2580000, 1221500)
|
||||
outring.AddPoint_2D(2580000, 1220500)
|
||||
polygon = ogr.Geometry(ogr.wkbPolygon)
|
||||
polygon.AddGeometry(outring)
|
||||
f.SetGeometry(polygon)
|
||||
@ -122,11 +125,11 @@ class TestPackageLayers(QgisTestCase):
|
||||
f = ogr.Feature(lyr.GetLayerDefn())
|
||||
f["name"] = "region two"
|
||||
outring = ogr.Geometry(ogr.wkbLinearRing)
|
||||
outring.AddPoint(2581000, 1220000)
|
||||
outring.AddPoint(2582000, 1220000)
|
||||
outring.AddPoint(2582000, 1221000)
|
||||
outring.AddPoint(2581000, 1221000)
|
||||
outring.AddPoint(2581000, 1220000)
|
||||
outring.AddPoint_2D(2581000, 1220000)
|
||||
outring.AddPoint_2D(2582000, 1220000)
|
||||
outring.AddPoint_2D(2582000, 1221000)
|
||||
outring.AddPoint_2D(2581000, 1221000)
|
||||
outring.AddPoint_2D(2581000, 1220000)
|
||||
polygon = ogr.Geometry(ogr.wkbPolygon)
|
||||
polygon.AddGeometry(outring)
|
||||
f.SetGeometry(polygon)
|
||||
@ -139,11 +142,11 @@ class TestPackageLayers(QgisTestCase):
|
||||
f["name"] = "province one"
|
||||
f["region"] = 1
|
||||
outring = ogr.Geometry(ogr.wkbLinearRing)
|
||||
outring.AddPoint(2580000, 1220500)
|
||||
outring.AddPoint(2580500, 1220500)
|
||||
outring.AddPoint(2580500, 1221500)
|
||||
outring.AddPoint(2580000, 1221500)
|
||||
outring.AddPoint(2580000, 1220500)
|
||||
outring.AddPoint_2D(2580000, 1220500)
|
||||
outring.AddPoint_2D(2580500, 1220500)
|
||||
outring.AddPoint_2D(2580500, 1221500)
|
||||
outring.AddPoint_2D(2580000, 1221500)
|
||||
outring.AddPoint_2D(2580000, 1220500)
|
||||
polygon = ogr.Geometry(ogr.wkbPolygon)
|
||||
polygon.AddGeometry(outring)
|
||||
f.SetGeometry(polygon)
|
||||
@ -152,11 +155,11 @@ class TestPackageLayers(QgisTestCase):
|
||||
f["name"] = "province two"
|
||||
f["region"] = 1
|
||||
outring = ogr.Geometry(ogr.wkbLinearRing)
|
||||
outring.AddPoint(2580500, 1220500)
|
||||
outring.AddPoint(2581000, 1220500)
|
||||
outring.AddPoint(2581000, 1221500)
|
||||
outring.AddPoint(2580500, 1221500)
|
||||
outring.AddPoint(2580500, 1220500)
|
||||
outring.AddPoint_2D(2580500, 1220500)
|
||||
outring.AddPoint_2D(2581000, 1220500)
|
||||
outring.AddPoint_2D(2581000, 1221500)
|
||||
outring.AddPoint_2D(2580500, 1221500)
|
||||
outring.AddPoint_2D(2580500, 1220500)
|
||||
polygon = ogr.Geometry(ogr.wkbPolygon)
|
||||
polygon.AddGeometry(outring)
|
||||
f.SetGeometry(polygon)
|
||||
@ -165,11 +168,11 @@ class TestPackageLayers(QgisTestCase):
|
||||
f["name"] = "province three"
|
||||
f["region"] = 2
|
||||
outring = ogr.Geometry(ogr.wkbLinearRing)
|
||||
outring.AddPoint(2581000, 1220000)
|
||||
outring.AddPoint(2582000, 1220000)
|
||||
outring.AddPoint(2582000, 1220500)
|
||||
outring.AddPoint(2581000, 1220500)
|
||||
outring.AddPoint(2581000, 1220000)
|
||||
outring.AddPoint_2D(2581000, 1220000)
|
||||
outring.AddPoint_2D(2582000, 1220000)
|
||||
outring.AddPoint_2D(2582000, 1220500)
|
||||
outring.AddPoint_2D(2581000, 1220500)
|
||||
outring.AddPoint_2D(2581000, 1220000)
|
||||
polygon = ogr.Geometry(ogr.wkbPolygon)
|
||||
polygon.AddGeometry(outring)
|
||||
f.SetGeometry(polygon)
|
||||
@ -178,11 +181,11 @@ class TestPackageLayers(QgisTestCase):
|
||||
f["name"] = "province four"
|
||||
f["region"] = 2
|
||||
outring = ogr.Geometry(ogr.wkbLinearRing)
|
||||
outring.AddPoint(2581000, 1220500)
|
||||
outring.AddPoint(2582000, 1220500)
|
||||
outring.AddPoint(2582000, 1221000)
|
||||
outring.AddPoint(2581000, 1221000)
|
||||
outring.AddPoint(2581000, 1220500)
|
||||
outring.AddPoint_2D(2581000, 1220500)
|
||||
outring.AddPoint_2D(2582000, 1220500)
|
||||
outring.AddPoint_2D(2582000, 1221000)
|
||||
outring.AddPoint_2D(2581000, 1221000)
|
||||
outring.AddPoint_2D(2581000, 1220500)
|
||||
polygon = ogr.Geometry(ogr.wkbPolygon)
|
||||
polygon.AddGeometry(outring)
|
||||
f.SetGeometry(polygon)
|
||||
@ -195,28 +198,28 @@ class TestPackageLayers(QgisTestCase):
|
||||
f["name"] = "city one"
|
||||
f["province"] = 1
|
||||
point = ogr.Geometry(ogr.wkbPoint)
|
||||
point.AddPoint(2580200, 1221200)
|
||||
point.AddPoint_2D(2580200, 1221200)
|
||||
f.SetGeometry(point)
|
||||
lyr.CreateFeature(f)
|
||||
f = ogr.Feature(lyr.GetLayerDefn())
|
||||
f["name"] = "city two"
|
||||
f["province"] = 1
|
||||
point = ogr.Geometry(ogr.wkbPoint)
|
||||
point.AddPoint(2580400, 1220700)
|
||||
point.AddPoint_2D(2580400, 1220700)
|
||||
f.SetGeometry(point)
|
||||
lyr.CreateFeature(f)
|
||||
f = ogr.Feature(lyr.GetLayerDefn())
|
||||
f["name"] = "city three"
|
||||
f["province"] = 2
|
||||
point = ogr.Geometry(ogr.wkbPoint)
|
||||
point.AddPoint(2580900, 1220900)
|
||||
point.AddPoint_2D(2580900, 1220900)
|
||||
f.SetGeometry(point)
|
||||
lyr.CreateFeature(f)
|
||||
f = ogr.Feature(lyr.GetLayerDefn())
|
||||
f["name"] = "city four"
|
||||
f["province"] = 4
|
||||
point = ogr.Geometry(ogr.wkbPoint)
|
||||
point.AddPoint(2581200, 1220300)
|
||||
point.AddPoint_2D(2581200, 1220300)
|
||||
f.SetGeometry(point)
|
||||
lyr.CreateFeature(f)
|
||||
|
||||
@ -466,6 +469,98 @@ class TestPackageLayers(QgisTestCase):
|
||||
province.selectByIds([])
|
||||
city.selectByIds([])
|
||||
|
||||
def test_crs(self):
|
||||
"""Test export with transformation"""
|
||||
|
||||
alg = self.registry.createAlgorithmById("qgis:package")
|
||||
self.assertIsNotNone(alg)
|
||||
|
||||
def _test(parameters, expected_wkts):
|
||||
|
||||
feedback = ConsoleFeedBack()
|
||||
context = QgsProcessingContext()
|
||||
context.setProject(QgsProject.instance())
|
||||
# Note: the following returns true also in case of errors ...
|
||||
self.assertTrue(execute(alg, parameters, context, feedback))
|
||||
# ... so we check the log
|
||||
self.assertEqual(feedback._errors, [])
|
||||
|
||||
# Check export
|
||||
for layer_name, wkts in expected_wkts.items():
|
||||
l = QgsVectorLayer(
|
||||
self.temp_export_path + f"|layername={layer_name}", layer_name
|
||||
)
|
||||
self.assertTrue(l.isValid())
|
||||
features = {f.id(): f for f in l.getFeatures()}
|
||||
self.assertCountEqual(
|
||||
list(features.keys()),
|
||||
list(wkts.keys()),
|
||||
layer_name + str(features.keys()),
|
||||
)
|
||||
for id, wkt in wkts.items():
|
||||
self.assertEqual(
|
||||
features[id].geometry().asWkt(3), wkt, f"{layer_name}: {id}"
|
||||
)
|
||||
|
||||
region = QgsProject.instance().mapLayersByName("region")[0]
|
||||
province = QgsProject.instance().mapLayersByName("province")[0]
|
||||
city = QgsProject.instance().mapLayersByName("city")[0]
|
||||
|
||||
parameters = {
|
||||
"EXPORT_RELATED_LAYERS": False,
|
||||
"LAYERS": [province, region, city],
|
||||
"OUTPUT": self.temp_export_path,
|
||||
"OVERWRITE": True,
|
||||
"SELECTED_FEATURES_ONLY": False,
|
||||
"EXTENT": None,
|
||||
"CRS": "EPSG:4326",
|
||||
}
|
||||
|
||||
# Test with no extent given
|
||||
_test(
|
||||
parameters,
|
||||
{
|
||||
"region": {
|
||||
1: "Polygon ((7.175 47.135, 7.188 47.135, 7.188 47.144, 7.175 47.144, 7.175 47.135))",
|
||||
2: "Polygon ((7.188 47.131, 7.201 47.131, 7.201 47.14, 7.188 47.14, 7.188 47.131))",
|
||||
},
|
||||
"province": {
|
||||
1: "Polygon ((7.175 47.135, 7.182 47.135, 7.182 47.144, 7.175 47.144, 7.175 47.135))",
|
||||
2: "Polygon ((7.182 47.135, 7.188 47.135, 7.188 47.144, 7.182 47.144, 7.182 47.135))",
|
||||
3: "Polygon ((7.188 47.131, 7.201 47.131, 7.201 47.135, 7.188 47.135, 7.188 47.131))",
|
||||
4: "Polygon ((7.188 47.135, 7.201 47.135, 7.201 47.14, 7.188 47.14, 7.188 47.135))",
|
||||
},
|
||||
"city": {
|
||||
1: "Point (7.178 47.141)",
|
||||
2: "Point (7.18 47.137)",
|
||||
3: "Point (7.187 47.139)",
|
||||
4: "Point (7.191 47.133)",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
# Test with extent
|
||||
# Test more interesting extent
|
||||
parameters["EXTENT"] = QgsReferencedRectangle(
|
||||
QgsRectangle(2580700, 1220000, 2581500, 1222000),
|
||||
QgsCoordinateReferenceSystem("EPSG:2056"),
|
||||
)
|
||||
_test(
|
||||
parameters,
|
||||
{
|
||||
"region": {
|
||||
1: "Polygon ((7.175 47.135, 7.188 47.135, 7.188 47.144, 7.175 47.144, 7.175 47.135))",
|
||||
2: "Polygon ((7.188 47.131, 7.201 47.131, 7.201 47.14, 7.188 47.14, 7.188 47.131))",
|
||||
},
|
||||
"province": {
|
||||
2: "Polygon ((7.182 47.135, 7.188 47.135, 7.188 47.144, 7.182 47.144, 7.182 47.135))",
|
||||
3: "Polygon ((7.188 47.131, 7.201 47.131, 7.201 47.135, 7.188 47.135, 7.188 47.131))",
|
||||
4: "Polygon ((7.188 47.135, 7.201 47.135, 7.201 47.14, 7.188 47.14, 7.188 47.135))",
|
||||
},
|
||||
"city": {3: "Point (7.187 47.139)", 4: "Point (7.191 47.133)"},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
Loading…
x
Reference in New Issue
Block a user