Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE][processing] Filter Vertices by M and Filter Vertices by Z a…
…lgorithms

Adds two new algorithms, for filtering line/polygon vertices by their
M or Z values. A minimum and maximum M/Z value can be entered, and
if the vertices fall outside these ranges they will be discarded
from the output geometry.

Both min and max filter value can also be data defined, so can
vary per feature.
  • Loading branch information
nyalldawson committed Jul 23, 2018
1 parent f685d11 commit 97e0db6
Show file tree
Hide file tree
Showing 41 changed files with 395 additions and 0 deletions.
Binary file not shown.
@@ -0,0 +1 @@
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
@@ -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"]]
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
@@ -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"]]
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
@@ -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"]]
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
@@ -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"]]
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
@@ -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"]]
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]
@@ -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"]]
Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions python/plugins/processing/tests/testdata/lines_z.cpg
@@ -0,0 +1 @@
UTF-8
Binary file added python/plugins/processing/tests/testdata/lines_z.dbf
Binary file not shown.
1 change: 1 addition & 0 deletions python/plugins/processing/tests/testdata/lines_z.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]]
1 change: 1 addition & 0 deletions python/plugins/processing/tests/testdata/lines_z.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"]]
Binary file added python/plugins/processing/tests/testdata/lines_z.shp
Binary file not shown.
Binary file added python/plugins/processing/tests/testdata/lines_z.shx
Binary file not shown.
74 changes: 74 additions & 0 deletions python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
Expand Up @@ -5818,4 +5818,78 @@ tests:
fields:
fid: skip

- algorithm: native:filterpointsbym
name: Filter by m no max
params:
INPUT:
name: lines_m.shp
type: vector
MIN: 0.6
results:
OUTPUT:
name: expected/filter_by_m_no_max.shp
type: vector

- algorithm: native:filterpointsbym
name: Filter by m no min
params:
INPUT:
name: lines_m.shp
type: vector
MAX: 0.6
results:
OUTPUT:
name: expected/filter_by_m_no_min.shp
type: vector

- algorithm: native:filterpointsbym
name: Filter by m
params:
INPUT:
name: lines_m.shp
type: vector
MAX: 0.7
MIN: 0.4
results:
OUTPUT:
name: expected/filter_by_m.shp
type: vector

- algorithm: native:filterpointsbyz
name: Filter by z no max
params:
INPUT:
name: lines_z.shp
type: vector
MIN: 0.6
results:
OUTPUT:
name: expected/filter_by_z_no_max.shp
type: vector

- algorithm: native:filterpointsbyz
name: Filter by z no min
params:
INPUT:
name: lines_z.shp
type: vector
MAX: 0.6
results:
OUTPUT:
name: expected/filter_by_z_no_min.shp
type: vector

- algorithm: native:filterpointsbyz
name: Filter by z
params:
INPUT:
name: lines_z.shp
type: vector
MAX: 0.7
MIN: 0.4
results:
OUTPUT:
name: expected/filter_by_z.shp
type: vector

# See ../README.md for a description of the file format
1 change: 1 addition & 0 deletions src/analysis/CMakeLists.txt
Expand Up @@ -42,6 +42,7 @@ SET(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmextractvertices.cpp
processing/qgsalgorithmfiledownloader.cpp
processing/qgsalgorithmfilter.cpp
processing/qgsalgorithmfilterpoints.cpp
processing/qgsalgorithmfixgeometries.cpp
processing/qgsalgorithmimportphotos.cpp
processing/qgsalgorithmintersection.cpp
Expand Down
194 changes: 194 additions & 0 deletions src/analysis/processing/qgsalgorithmfilterpoints.cpp
@@ -0,0 +1,194 @@
/***************************************************************************
qgsalgorithmfilterpoints.cpp
----------------------------
begin : July 2018
copyright : (C) 2018 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 "qgsalgorithmfilterpoints.h"

///@cond PRIVATE


QString QgsFilterPointsAlgorithmBase::group() const
{
return QObject::tr( "Vector geometry" );
}

QString QgsFilterPointsAlgorithmBase::groupId() const
{
return QStringLiteral( "vectorgeometry" );
}

QString QgsFilterPointsAlgorithmBase::outputName() const
{
return QObject::tr( "Filtered" );
}

QString QgsFilterPointsAlgorithmBase::shortHelpString() const
{
return QObject::tr( "Filters away vertices based on their %1, returning geometries with only "
"vertex points that have a %1 ≥ the specified minimum value and ≤ "
"the maximum value.\n\n"
"If the minimum value is not specified than only the maximum value is tested, "
"and similarly if the maximum value is not specified than only the minimum value is tested.\n\n"
"The resultant geometries created by this algorithm may not be valid "
"and may need to be run through the \"Repair geometries\" algorithm to ensure "
"their validity." ).arg( componentString() );
}

QList<int> QgsFilterPointsAlgorithmBase::inputLayerTypes() const
{
return QList<int>() << QgsProcessing::TypeVectorLine << QgsProcessing::TypeVectorPolygon;
}

void QgsFilterPointsAlgorithmBase::initParameters( const QVariantMap & )
{
auto min = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "MIN" ),
QObject::tr( "Minimum" ), QgsProcessingParameterNumber::Double, QVariant(), true );
min->setIsDynamic( true );
min->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "Minimum" ), QObject::tr( "Minimum value" ), QgsPropertyDefinition::Double ) );
min->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
addParameter( min.release() );

auto max = qgis::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "MAX" ),
QObject::tr( "Maximum" ), QgsProcessingParameterNumber::Double, QVariant(), true );
max->setIsDynamic( true );
max->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "Maximum" ), QObject::tr( "Maximum value" ), QgsPropertyDefinition::Double ) );
max->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
addParameter( max.release() );
}

bool QgsFilterPointsAlgorithmBase::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback * )
{
if ( parameters.contains( QStringLiteral( "MIN" ) ) && parameters.value( QStringLiteral( "MIN" ) ).isValid() )
mMin = parameterAsDouble( parameters, QStringLiteral( "MIN" ), context );
else
mMin = std::numeric_limits<double>::quiet_NaN();

mDynamicMin = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "MIN" ) );
if ( mDynamicMin )
mMinProperty = parameters.value( QStringLiteral( "MIN" ) ).value< QgsProperty >();

if ( parameters.contains( QStringLiteral( "MAX" ) ) && parameters.value( QStringLiteral( "MAX" ) ).isValid() )
mMax = parameterAsDouble( parameters, QStringLiteral( "MAX" ), context );
else
mMax = std::numeric_limits<double>::quiet_NaN();

mDynamicMax = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "MAX" ) );
if ( mDynamicMax )
mMaxProperty = parameters.value( QStringLiteral( "MAX" ) ).value< QgsProperty >();

return true;
}

QgsFeatureList QgsFilterPointsAlgorithmBase::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback * )
{
QgsFeature f = feature;
if ( f.hasGeometry() )
{
QgsGeometry geometry = f.geometry();
double min = mMin;
if ( mDynamicMin )
min = mMinProperty.valueAsDouble( context.expressionContext(), std::numeric_limits<double>::quiet_NaN() );

double max = mMax;
if ( mDynamicMax )
max = mMaxProperty.valueAsDouble( context.expressionContext(), std::numeric_limits<double>::quiet_NaN() );

filter( geometry, min, max );
f.setGeometry( geometry );
}
return QgsFeatureList() << f;
}

//
// QgsFilterPointsByM
//

QString QgsFilterPointsByM::name() const
{
return QStringLiteral( "filterpointsbym" );
}

QString QgsFilterPointsByM::displayName() const
{
return QObject::tr( "Filter vertices by m value" );
}

QStringList QgsFilterPointsByM::tags() const
{
return QObject::tr( "filter,points,vertex,m" ).split( ',' );
}

QgsFilterPointsByM *QgsFilterPointsByM::createInstance() const
{
return new QgsFilterPointsByM();
}

QString QgsFilterPointsByM::componentString() const
{
return QObject::tr( "m-value" );
}

void QgsFilterPointsByM::filter( QgsGeometry &geometry, double min, double max ) const
{
geometry.filterVertices( [min, max]( const QgsPoint & point )->bool
{
return ( std::isnan( min ) || point.m() >= min )
&& ( std::isnan( max ) || point.m() <= max );
} );
}


//
// QgsFilterPointsByZ
//

QString QgsFilterPointsByZ::name() const
{
return QStringLiteral( "filterpointsbyz" );
}

QString QgsFilterPointsByZ::displayName() const
{
return QObject::tr( "Filter vertices by z value" );
}

QStringList QgsFilterPointsByZ::tags() const
{
return QObject::tr( "filter,points,vertex,z" ).split( ',' );
}

QgsFilterPointsByZ *QgsFilterPointsByZ::createInstance() const
{
return new QgsFilterPointsByZ();
}

QString QgsFilterPointsByZ::componentString() const
{
return QObject::tr( "z-value" );
}

void QgsFilterPointsByZ::filter( QgsGeometry &geometry, double min, double max ) const
{
geometry.filterVertices( [min, max]( const QgsPoint & point )->bool
{
return ( std::isnan( min ) || point.z() >= min )
&& ( std::isnan( max ) || point.z() <= max );
} );
}

///@endcond


0 comments on commit 97e0db6

Please sign in to comment.