diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_all.dbf b/python/plugins/processing/tests/testdata/expected/extract_m_all.dbf new file mode 100644 index 00000000000..6ae7255219d Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_m_all.dbf differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_all.prj b/python/plugins/processing/tests/testdata/expected/extract_m_all.prj new file mode 100644 index 00000000000..a30c00a55de --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_m_all.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] \ No newline at end of file diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_all.qpj b/python/plugins/processing/tests/testdata/expected/extract_m_all.qpj new file mode 100644 index 00000000000..5fbc831e743 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_m_all.qpj @@ -0,0 +1 @@ +GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_all.shp b/python/plugins/processing/tests/testdata/expected/extract_m_all.shp new file mode 100644 index 00000000000..6b465867962 Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_m_all.shp differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_all.shx b/python/plugins/processing/tests/testdata/expected/extract_m_all.shx new file mode 100644 index 00000000000..24333223734 Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_m_all.shx differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_first.dbf b/python/plugins/processing/tests/testdata/expected/extract_m_first.dbf new file mode 100644 index 00000000000..dc462e67009 Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_m_first.dbf differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_first.prj b/python/plugins/processing/tests/testdata/expected/extract_m_first.prj new file mode 100644 index 00000000000..a30c00a55de --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_m_first.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] \ No newline at end of file diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_first.qpj b/python/plugins/processing/tests/testdata/expected/extract_m_first.qpj new file mode 100644 index 00000000000..5fbc831e743 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_m_first.qpj @@ -0,0 +1 @@ +GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_first.shp b/python/plugins/processing/tests/testdata/expected/extract_m_first.shp new file mode 100644 index 00000000000..6b465867962 Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_m_first.shp differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_first.shx b/python/plugins/processing/tests/testdata/expected/extract_m_first.shx new file mode 100644 index 00000000000..24333223734 Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_m_first.shx differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_none.dbf b/python/plugins/processing/tests/testdata/expected/extract_m_none.dbf new file mode 100644 index 00000000000..79e30bb549d Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_m_none.dbf differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_none.prj b/python/plugins/processing/tests/testdata/expected/extract_m_none.prj new file mode 100644 index 00000000000..a30c00a55de --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_m_none.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] \ No newline at end of file diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_none.qpj b/python/plugins/processing/tests/testdata/expected/extract_m_none.qpj new file mode 100644 index 00000000000..5fbc831e743 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_m_none.qpj @@ -0,0 +1 @@ +GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_none.shp b/python/plugins/processing/tests/testdata/expected/extract_m_none.shp new file mode 100644 index 00000000000..a0a4405be68 Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_m_none.shp differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_none.shx b/python/plugins/processing/tests/testdata/expected/extract_m_none.shx new file mode 100644 index 00000000000..7699aa20d55 Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_m_none.shx differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_points.dbf b/python/plugins/processing/tests/testdata/expected/extract_m_points.dbf new file mode 100644 index 00000000000..e01840c427e Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_m_points.dbf differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_points.prj b/python/plugins/processing/tests/testdata/expected/extract_m_points.prj new file mode 100644 index 00000000000..a30c00a55de --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_m_points.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] \ No newline at end of file diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_points.qpj b/python/plugins/processing/tests/testdata/expected/extract_m_points.qpj new file mode 100644 index 00000000000..5fbc831e743 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_m_points.qpj @@ -0,0 +1 @@ +GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_points.shp b/python/plugins/processing/tests/testdata/expected/extract_m_points.shp new file mode 100644 index 00000000000..0231b3a5a81 Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_m_points.shp differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_m_points.shx b/python/plugins/processing/tests/testdata/expected/extract_m_points.shx new file mode 100644 index 00000000000..c219ef372ee Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_m_points.shx differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_all.dbf b/python/plugins/processing/tests/testdata/expected/extract_z_all.dbf new file mode 100644 index 00000000000..e6eeb46d176 Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_z_all.dbf differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_all.prj b/python/plugins/processing/tests/testdata/expected/extract_z_all.prj new file mode 100644 index 00000000000..a30c00a55de --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_z_all.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] \ No newline at end of file diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_all.qpj b/python/plugins/processing/tests/testdata/expected/extract_z_all.qpj new file mode 100644 index 00000000000..5fbc831e743 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_z_all.qpj @@ -0,0 +1 @@ +GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_all.shp b/python/plugins/processing/tests/testdata/expected/extract_z_all.shp new file mode 100644 index 00000000000..c6769961e9e Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_z_all.shp differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_all.shx b/python/plugins/processing/tests/testdata/expected/extract_z_all.shx new file mode 100644 index 00000000000..2b1a727a663 Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_z_all.shx differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_first.dbf b/python/plugins/processing/tests/testdata/expected/extract_z_first.dbf new file mode 100644 index 00000000000..94ded4ae66f Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_z_first.dbf differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_first.prj b/python/plugins/processing/tests/testdata/expected/extract_z_first.prj new file mode 100644 index 00000000000..a30c00a55de --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_z_first.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] \ No newline at end of file diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_first.qpj b/python/plugins/processing/tests/testdata/expected/extract_z_first.qpj new file mode 100644 index 00000000000..5fbc831e743 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_z_first.qpj @@ -0,0 +1 @@ +GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_first.shp b/python/plugins/processing/tests/testdata/expected/extract_z_first.shp new file mode 100644 index 00000000000..c6769961e9e Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_z_first.shp differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_first.shx b/python/plugins/processing/tests/testdata/expected/extract_z_first.shx new file mode 100644 index 00000000000..2b1a727a663 Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_z_first.shx differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_none.dbf b/python/plugins/processing/tests/testdata/expected/extract_z_none.dbf new file mode 100644 index 00000000000..448bb844ea6 Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_z_none.dbf differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_none.prj b/python/plugins/processing/tests/testdata/expected/extract_z_none.prj new file mode 100644 index 00000000000..a30c00a55de --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_z_none.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] \ No newline at end of file diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_none.qpj b/python/plugins/processing/tests/testdata/expected/extract_z_none.qpj new file mode 100644 index 00000000000..5fbc831e743 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_z_none.qpj @@ -0,0 +1 @@ +GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_none.shp b/python/plugins/processing/tests/testdata/expected/extract_z_none.shp new file mode 100644 index 00000000000..27dd420e40c Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_z_none.shp differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_none.shx b/python/plugins/processing/tests/testdata/expected/extract_z_none.shx new file mode 100644 index 00000000000..a0a0c32ec7b Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_z_none.shx differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_points.dbf b/python/plugins/processing/tests/testdata/expected/extract_z_points.dbf new file mode 100644 index 00000000000..7a23aaadb7f Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_z_points.dbf differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_points.prj b/python/plugins/processing/tests/testdata/expected/extract_z_points.prj new file mode 100644 index 00000000000..a30c00a55de --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_z_points.prj @@ -0,0 +1 @@ +GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]] \ No newline at end of file diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_points.qpj b/python/plugins/processing/tests/testdata/expected/extract_z_points.qpj new file mode 100644 index 00000000000..5fbc831e743 --- /dev/null +++ b/python/plugins/processing/tests/testdata/expected/extract_z_points.qpj @@ -0,0 +1 @@ +GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]] diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_points.shp b/python/plugins/processing/tests/testdata/expected/extract_z_points.shp new file mode 100644 index 00000000000..0231b3a5a81 Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_z_points.shp differ diff --git a/python/plugins/processing/tests/testdata/expected/extract_z_points.shx b/python/plugins/processing/tests/testdata/expected/extract_z_points.shx new file mode 100644 index 00000000000..c219ef372ee Binary files /dev/null and b/python/plugins/processing/tests/testdata/expected/extract_z_points.shx differ diff --git a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml index 5c2b131a906..9ebcab0182e 100755 --- a/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml +++ b/python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml @@ -6430,6 +6430,178 @@ tests: name: expected/force_rhr_multipolys.gml type: vector + - algorithm: native:extractzvalues + name: Extract z, first value only + params: + COLUMN_PREFIX: z_ + INPUT: + name: lines_z.shp + type: vector + SUMMARIES: + - 0 + results: + OUTPUT: + name: expected/extract_z_first.shp + type: vector + + - algorithm: native:extractzvalues + name: Extract z, all stats + params: + COLUMN_PREFIX: zs_ + INPUT: + name: lines_z.shp + type: vector + SUMMARIES: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + - 9 + - 10 + - 11 + - 12 + - 13 + - 14 + - 15 + results: + OUTPUT: + name: expected/extract_z_all.shp + type: vector + + - algorithm: native:extractzvalues + name: Extract z, points + params: + COLUMN_PREFIX: z_ + INPUT: + name: custom/pointszm.shp + type: vector + SUMMARIES: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + - 9 + - 10 + - 11 + - 12 + - 13 + - 14 + - 15 + results: + OUTPUT: + name: expected/extract_z_points.shp + type: vector + + - algorithm: native:extractzvalues + name: Extract z, no z values + params: + COLUMN_PREFIX: z_ + INPUT: + name: lines.gml|layername=lines + type: vector + SUMMARIES: + - 0 + results: + OUTPUT: + name: expected/extract_z_none.shp + type: vector + + - algorithm: native:extractmvalues + name: Extract m first only + params: + COLUMN_PREFIX: m_ + INPUT: + name: lines_m.shp + type: vector + SUMMARIES: + - 0 + results: + OUTPUT: + name: expected/extract_m_first.shp + type: vector + + - algorithm: native:extractmvalues + name: Extract m, all stats + params: + COLUMN_PREFIX: ms_ + INPUT: + name: lines_m.shp + type: vector + SUMMARIES: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + - 9 + - 10 + - 11 + - 12 + - 13 + - 14 + - 15 + results: + OUTPUT: + name: expected/extract_m_all.shp + type: vector + + - algorithm: native:extractmvalues + name: Extract m, points + params: + COLUMN_PREFIX: mp_ + INPUT: + name: custom/pointszm.shp + type: vector + SUMMARIES: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + - 9 + - 10 + - 11 + - 12 + - 13 + - 14 + - 15 + results: + OUTPUT: + name: expected/extract_m_points.shp + type: vector + + - algorithm: native:extractmvalues + name: Extract m, no m values present + params: + COLUMN_PREFIX: m_ + INPUT: + name: points.gml|layername=points + type: vector + SUMMARIES: + - 0 + results: + OUTPUT: + name: expected/extract_m_none.shp + type: vector + - algorithm: native:splitlinesbylength name: Split multilines by length params: diff --git a/src/analysis/CMakeLists.txt b/src/analysis/CMakeLists.txt index 54834433753..8302cca473b 100644 --- a/src/analysis/CMakeLists.txt +++ b/src/analysis/CMakeLists.txt @@ -46,6 +46,7 @@ SET(QGIS_ANALYSIS_SRCS processing/qgsalgorithmextractbyexpression.cpp processing/qgsalgorithmextractbyextent.cpp processing/qgsalgorithmextractbylocation.cpp + processing/qgsalgorithmextractzmvalues.cpp processing/qgsalgorithmextractvertices.cpp processing/qgsalgorithmfiledownloader.cpp processing/qgsalgorithmfilter.cpp diff --git a/src/analysis/processing/qgsalgorithmextractzmvalues.cpp b/src/analysis/processing/qgsalgorithmextractzmvalues.cpp new file mode 100644 index 00000000000..1eeae845b80 --- /dev/null +++ b/src/analysis/processing/qgsalgorithmextractzmvalues.cpp @@ -0,0 +1,245 @@ +/*************************************************************************** + qgsalgorithmextractzmvalues.cpp + --------------------------------- + begin : January 2019 + copyright : (C) 2019 by Nyall Dawson + email : nyall dot dawson at gmail dot com + ***************************************************************************/ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "qgsalgorithmextractzmvalues.h" +#include "qgsfeaturerequest.h" +#include + +///@cond PRIVATE + +const std::vector< QgsStatisticalSummary::Statistic > STATS +{ + QgsStatisticalSummary::First, + QgsStatisticalSummary::Last, + QgsStatisticalSummary::Count, + QgsStatisticalSummary::Sum, + QgsStatisticalSummary::Mean, + QgsStatisticalSummary::Median, + QgsStatisticalSummary::StDev, + QgsStatisticalSummary::Min, + QgsStatisticalSummary::Max, + QgsStatisticalSummary::Range, + QgsStatisticalSummary::Minority, + QgsStatisticalSummary::Majority, + QgsStatisticalSummary::Variety, + QgsStatisticalSummary::FirstQuartile, + QgsStatisticalSummary::ThirdQuartile, + QgsStatisticalSummary::InterQuartileRange, +}; + +QString QgsExtractZMValuesAlgorithmBase::group() const +{ + return QObject::tr( "Vector geometry" ); +} + +QString QgsExtractZMValuesAlgorithmBase::groupId() const +{ + return QStringLiteral( "vectorgeometry" ); +} + +QString QgsExtractZMValuesAlgorithmBase::outputName() const +{ + return QObject::tr( "Extracted" ); +} + +QList QgsExtractZMValuesAlgorithmBase::inputLayerTypes() const +{ + return QList() << QgsProcessing::TypeVectorAnyGeometry; +} + +QgsProcessingFeatureSource::Flag QgsExtractZMValuesAlgorithmBase::sourceFlags() const +{ + return QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks; +} + +void QgsExtractZMValuesAlgorithmBase::initParameters( const QVariantMap & ) +{ + QStringList statChoices; + statChoices.reserve( STATS.size() ); + for ( QgsStatisticalSummary::Statistic stat : STATS ) + { + statChoices << QgsStatisticalSummary::displayName( stat ); + } + + addParameter( new QgsProcessingParameterEnum( QStringLiteral( "SUMMARIES" ), + QObject::tr( "Summaries to calculate" ), + statChoices, true, QVariantList() << 0 ) ); + + addParameter( new QgsProcessingParameterString( QStringLiteral( "COLUMN_PREFIX" ), QObject::tr( "Output column prefix" ), mDefaultFieldPrefix, false, true ) ); +} + +QgsFields QgsExtractZMValuesAlgorithmBase::outputFields( const QgsFields &inputFields ) const +{ + return QgsProcessingUtils::combineFields( inputFields, mNewFields ); +} + +bool QgsExtractZMValuesAlgorithmBase::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * ) +{ + mPrefix = parameterAsString( parameters, QStringLiteral( "COLUMN_PREFIX" ), context ); + + const QList< int > stats = parameterAsEnums( parameters, QStringLiteral( "SUMMARIES" ), context ); + mStats = nullptr; + for ( int s : stats ) + { + mStats |= STATS.at( s ); + mSelectedStats << STATS.at( s ); + mNewFields.append( QgsField( mPrefix + QgsStatisticalSummary::shortName( STATS.at( s ) ), STATS.at( s ) == QgsStatisticalSummary::Count || STATS.at( s ) == QgsStatisticalSummary::Variety ? QVariant::Int : QVariant::Double ) ); + } + + return true; +} + +QgsFeatureList QgsExtractZMValuesAlgorithmBase::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback * ) +{ + QgsFeature f = feature; + QgsAttributes attrs = f.attributes(); + attrs.reserve( attrs.count() + mSelectedStats.count() ); + if ( !f.hasGeometry() || f.geometry().isEmpty() || !mTestGeomFunc( f.geometry() ) ) + { + attrs.resize( attrs.count() + mNewFields.size() ); + } + else + { + const QgsGeometry g = f.geometry(); + QgsStatisticalSummary stat( mStats ); + for ( auto it = g.vertices_begin(); it != g.vertices_end(); ++it ) + { + stat.addValue( mExtractValFunc( *it ) ); + if ( mStats == QgsStatisticalSummary::First ) + { + // only retrieving first vertex info (default behavior), so short cut and + // don't iterate remaining vertices + break; + } + } + stat.finalize(); + + for ( QgsStatisticalSummary::Statistic s : qgis::as_const( mSelectedStats ) ) + attrs.append( stat.statistic( s ) ); + } + f.setAttributes( attrs ); + + return QgsFeatureList() << f; +} + +bool QgsExtractZMValuesAlgorithmBase::supportInPlaceEdit( const QgsMapLayer *layer ) const +{ + Q_UNUSED( layer ); + return false; +} + +// +// QgsExtractZValuesAlgorithm +// + +QgsExtractZValuesAlgorithm::QgsExtractZValuesAlgorithm() +{ + mExtractValFunc = []( const QgsPoint & p ) -> double + { + return p.z(); + }; + mTestGeomFunc = []( const QgsGeometry & g ) -> bool + { + return QgsWkbTypes::hasZ( g.wkbType() ); + }; + mDefaultFieldPrefix = QStringLiteral( "z_" ); +} + +QString QgsExtractZValuesAlgorithm::name() const +{ + return QStringLiteral( "extractzvalues" ); +} + +QString QgsExtractZValuesAlgorithm::displayName() const +{ + return QObject::tr( "Extract Z values" ); +} + +QgsProcessingAlgorithm *QgsExtractZValuesAlgorithm::createInstance() const +{ + return new QgsExtractZValuesAlgorithm(); +} + +QStringList QgsExtractZValuesAlgorithm::tags() const +{ + return QObject::tr( "add,z,value,elevation,height,attribute,statistics,stats" ).split( ',' ); +} + +QString QgsExtractZValuesAlgorithm::shortHelpString() const +{ + return QObject::tr( "Extracts z values from geometries into feature attributes.\n\n" + "By default only the z value from the first vertex of each feature is extracted, however the algorithm " + "can optionally calculate statistics on all of the geometry's z values, including sums, means, and minimums and maximums" ); +} + +QString QgsExtractZValuesAlgorithm::shortDescription() const +{ + return QObject::tr( "Extracts z values (or z value statistics) from geometries into feature attributes." ); +} + + +// +// QgsExtractMValuesAlgorithm +// + +QgsExtractMValuesAlgorithm::QgsExtractMValuesAlgorithm() +{ + mExtractValFunc = []( const QgsPoint & p ) -> double + { + return p.m(); + }; + mTestGeomFunc = []( const QgsGeometry & g ) -> bool + { + return QgsWkbTypes::hasM( g.wkbType() ); + }; + mDefaultFieldPrefix = QStringLiteral( "m_" ); +} + +QString QgsExtractMValuesAlgorithm::name() const +{ + return QStringLiteral( "extractmvalues" ); +} + +QString QgsExtractMValuesAlgorithm::displayName() const +{ + return QObject::tr( "Extract M values" ); +} + +QgsProcessingAlgorithm *QgsExtractMValuesAlgorithm::createInstance() const +{ + return new QgsExtractMValuesAlgorithm(); +} + +QStringList QgsExtractMValuesAlgorithm::tags() const +{ + return QObject::tr( "add,m,value,measure,attribute,statistics,stats" ).split( ',' ); +} + +QString QgsExtractMValuesAlgorithm::shortHelpString() const +{ + return QObject::tr( "Extracts m values from geometries into feature attributes.\n\n" + "By default only the m value from the first vertex of each feature is extracted, however the algorithm " + "can optionally calculate statistics on all of the geometry's m values, including sums, means, and minimums and maximums" ); +} + +QString QgsExtractMValuesAlgorithm::shortDescription() const +{ + return QObject::tr( "Extracts m values (or m value statistics) from geometries into feature attributes." ); +} + + +///@endcond + diff --git a/src/analysis/processing/qgsalgorithmextractzmvalues.h b/src/analysis/processing/qgsalgorithmextractzmvalues.h new file mode 100644 index 00000000000..094ec377a73 --- /dev/null +++ b/src/analysis/processing/qgsalgorithmextractzmvalues.h @@ -0,0 +1,108 @@ +/*************************************************************************** + qgsalgorithmextractzmvalues.h + --------------------------------- + begin : January 2019 + copyright : (C) 2019 by Nyall Dawson + email : nyall dot dawson at gmail dot com + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef QGSALGORITHMEXTRACTZMVALUES_H +#define QGSALGORITHMEXTRACTZMVALUES_H + +#define SIP_NO_FILE + +#include "qgis.h" +#include "qgsprocessingalgorithm.h" +#include "qgsstatisticalsummary.h" +#include + +///@cond PRIVATE + +/** + * Native add incremental field algorithm. + */ +class QgsExtractZMValuesAlgorithmBase : public QgsProcessingFeatureBasedAlgorithm +{ + + public: + + QgsExtractZMValuesAlgorithmBase() = default; + QString group() const override; + QString groupId() const override; + QList inputLayerTypes() const override; + + protected: + + void initParameters( const QVariantMap &configuration = QVariantMap() ) override; + QString outputName() const override; + QgsFields outputFields( const QgsFields &inputFields ) const override; + QgsProcessingFeatureSource::Flag sourceFlags() const override; + + bool prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override; + QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override; + bool supportInPlaceEdit( const QgsMapLayer *layer ) const override; + + protected: + + std::function mExtractValFunc; + std::function mTestGeomFunc; + QString mDefaultFieldPrefix; + private: + + QList< QgsStatisticalSummary::Statistic > mSelectedStats; + QgsStatisticalSummary::Statistics mStats = QgsStatisticalSummary::All; + QString mPrefix; + QgsFields mNewFields; + + +}; + +/** + * Native extract z values algorithm. + */ +class QgsExtractZValuesAlgorithm : public QgsExtractZMValuesAlgorithmBase +{ + public: + QgsExtractZValuesAlgorithm(); + + QString name() const override; + QString displayName() const override; + QgsProcessingAlgorithm *createInstance() const override; + QStringList tags() const override; + QString shortHelpString() const override; + QString shortDescription() const override; + +}; + + +/** + * Native extract m values algorithm. + */ +class QgsExtractMValuesAlgorithm : public QgsExtractZMValuesAlgorithmBase +{ + public: + QgsExtractMValuesAlgorithm(); + + QString name() const override; + QString displayName() const override; + QgsProcessingAlgorithm *createInstance() const override; + QStringList tags() const override; + QString shortHelpString() const override; + QString shortDescription() const override; + +}; + +///@endcond PRIVATE + +#endif // QGSALGORITHMEXTRACTZMVALUES_H + + diff --git a/src/analysis/processing/qgsnativealgorithms.cpp b/src/analysis/processing/qgsnativealgorithms.cpp index 03600f0c0d1..7b99c272960 100644 --- a/src/analysis/processing/qgsnativealgorithms.cpp +++ b/src/analysis/processing/qgsnativealgorithms.cpp @@ -42,6 +42,7 @@ #include "qgsalgorithmextractbyextent.h" #include "qgsalgorithmextractbylocation.h" #include "qgsalgorithmextractvertices.h" +#include "qgsalgorithmextractzmvalues.h" #include "qgsalgorithmfiledownloader.h" #include "qgsalgorithmfilter.h" #include "qgsalgorithmfiltervertices.h" @@ -171,7 +172,9 @@ void QgsNativeAlgorithms::loadAlgorithms() addAlgorithm( new QgsExtractByExpressionAlgorithm() ); addAlgorithm( new QgsExtractByExtentAlgorithm() ); addAlgorithm( new QgsExtractByLocationAlgorithm() ); + addAlgorithm( new QgsExtractMValuesAlgorithm() ); addAlgorithm( new QgsExtractVerticesAlgorithm() ); + addAlgorithm( new QgsExtractZValuesAlgorithm() ); addAlgorithm( new QgsFileDownloaderAlgorithm() ); addAlgorithm( new QgsFilterAlgorithm() ); addAlgorithm( new QgsFilterVerticesByM() );