Skip to content

Commit b391c08

Browse files
authoredJan 21, 2019
Merge pull request #8923 from m-kuhn/native_densify_by_interval
Add native densify by interval algorithm
2 parents b6f7176 + 25acd79 commit b391c08

File tree

7 files changed

+268
-83
lines changed

7 files changed

+268
-83
lines changed
 

‎python/plugins/processing/algs/qgis/DensifyGeometriesInterval.py

Lines changed: 0 additions & 77 deletions
This file was deleted.

‎python/plugins/processing/algs/qgis/QgisAlgorithmProvider.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@
6161
from .DeleteColumn import DeleteColumn
6262
from .DeleteDuplicateGeometries import DeleteDuplicateGeometries
6363
from .DensifyGeometries import DensifyGeometries
64-
from .DensifyGeometriesInterval import DensifyGeometriesInterval
6564
from .EliminateSelection import EliminateSelection
6665
from .ExecuteSQL import ExecuteSQL
6766
from .ExportGeometryInfo import ExportGeometryInfo
@@ -172,7 +171,6 @@ def getAlgs(self):
172171
DeleteColumn(),
173172
DeleteDuplicateGeometries(),
174173
DensifyGeometries(),
175-
DensifyGeometriesInterval(),
176174
EliminateSelection(),
177175
ExecuteSQL(),
178176
ExportGeometryInfo(),

‎src/analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ SET(QGIS_ANALYSIS_SRCS
3232
processing/qgsalgorithmclip.cpp
3333
processing/qgsalgorithmconvexhull.cpp
3434
processing/qgsalgorithmdbscanclustering.cpp
35+
processing/qgsalgorithmdensifygeometriesbyinterval.cpp
3536
processing/qgsalgorithmdifference.cpp
3637
processing/qgsalgorithmdissolve.cpp
3738
processing/qgsalgorithmdrape.cpp
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/***************************************************************************
2+
qgsalgorithmdensifygeometries.cpp
3+
---------------------
4+
begin : January 2019
5+
copyright : (C) 2019 by Matthias Kuhn
6+
email : matthias@opengis.ch
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
19+
#include "qgsalgorithmdensifygeometriesbyinterval.h"
20+
21+
///@cond PRIVATE
22+
23+
QString QgsDensifyGeometriesByIntervalAlgorithm::name() const
24+
{
25+
return QStringLiteral( "densifygeometriesgivenaninterval" );
26+
}
27+
28+
QString QgsDensifyGeometriesByIntervalAlgorithm::displayName() const
29+
{
30+
return QObject::tr( "Densify by interval" );
31+
}
32+
33+
QStringList QgsDensifyGeometriesByIntervalAlgorithm::tags() const
34+
{
35+
return QObject::tr( "add,vertex,vertices,points,nodes" ).split( ',' );
36+
}
37+
38+
QString QgsDensifyGeometriesByIntervalAlgorithm::group() const
39+
{
40+
return QObject::tr( "Vector geometry" );
41+
}
42+
43+
QString QgsDensifyGeometriesByIntervalAlgorithm::groupId() const
44+
{
45+
return QStringLiteral( "vectorgeometry" );
46+
}
47+
48+
QString QgsDensifyGeometriesByIntervalAlgorithm::shortHelpString() const
49+
{
50+
return QObject::tr( "Geometries are densified by adding additional vertices on "
51+
"edges that have a maximum distance of the interval parameter "
52+
"in map units." );
53+
}
54+
55+
QString QgsDensifyGeometriesByIntervalAlgorithm::shortDescription() const
56+
{
57+
return QObject::tr( "Creates a densified version of geometries." );
58+
}
59+
60+
QgsDensifyGeometriesByIntervalAlgorithm *QgsDensifyGeometriesByIntervalAlgorithm::createInstance() const
61+
{
62+
return new QgsDensifyGeometriesByIntervalAlgorithm;
63+
64+
}
65+
66+
QList<int> QgsDensifyGeometriesByIntervalAlgorithm::inputLayerTypes() const
67+
{
68+
return QList<int>() << QgsProcessing::TypeVectorLine << QgsProcessing::TypeVectorPolygon;
69+
}
70+
71+
void QgsDensifyGeometriesByIntervalAlgorithm::initParameters( const QVariantMap &configuration )
72+
{
73+
Q_UNUSED( configuration )
74+
std::unique_ptr<QgsProcessingParameterDistance> interval = qgis::make_unique<QgsProcessingParameterDistance>( QStringLiteral( "INTERVAL" ),
75+
QObject::tr( "Interval between vertices to add" ),
76+
1, QStringLiteral( "INPUT" ), false, 0, 10000000 );
77+
interval->setIsDynamic( true );
78+
interval->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "Interval" ), QObject::tr( "Interval" ), QgsPropertyDefinition::DoublePositive ) );
79+
interval->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) );
80+
addParameter( interval.release() );
81+
}
82+
83+
QString QgsDensifyGeometriesByIntervalAlgorithm::outputName() const
84+
{
85+
return QObject::tr( "Densified" );
86+
}
87+
88+
QgsFeatureList QgsDensifyGeometriesByIntervalAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
89+
{
90+
Q_UNUSED( context );
91+
Q_UNUSED( feedback );
92+
QgsFeature modifiedFeature = feature;
93+
94+
double interval = mInterval;
95+
if ( mDynamicInterval )
96+
interval = mIntervalProperty.valueAsDouble( context.expressionContext(), interval );
97+
98+
if ( feature.hasGeometry() )
99+
modifiedFeature.setGeometry( feature.geometry().densifyByDistance( mInterval ) );
100+
101+
return QgsFeatureList() << modifiedFeature;
102+
}
103+
104+
bool QgsDensifyGeometriesByIntervalAlgorithm::prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
105+
{
106+
Q_UNUSED( feedback );
107+
mInterval = parameterAsDouble( parameters, QStringLiteral( "INTERVAL" ), context );
108+
109+
mDynamicInterval = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "INTERVAL" ) );
110+
if ( mDynamicInterval )
111+
mIntervalProperty = parameters.value( QStringLiteral( "INTERVAL" ) ).value< QgsProperty >();
112+
113+
return true;
114+
}
115+
116+
///@endcond PRIVATE
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/***************************************************************************
2+
qgsalgorithmdensifygeometries.h
3+
---------------------
4+
begin : January 2019
5+
copyright : (C) 2019 by Matthias Kuhn
6+
email : matthias@opengis.ch
7+
***************************************************************************/
8+
9+
/***************************************************************************
10+
* *
11+
* This program is free software; you can redistribute it and/or modify *
12+
* it under the terms of the GNU General Public License as published by *
13+
* the Free Software Foundation; either version 2 of the License, or *
14+
* (at your option) any later version. *
15+
* *
16+
***************************************************************************/
17+
18+
#ifndef QGSALGORITHMDENSIFYGEOMETRIES_H
19+
#define QGSALGORITHMDENSIFYGEOMETRIES_H
20+
21+
#define SIP_NO_FILE
22+
23+
#include "qgis.h"
24+
#include "qgsprocessingalgorithm.h"
25+
26+
///@cond PRIVATE
27+
28+
29+
class QgsDensifyGeometriesByIntervalAlgorithm : public QgsProcessingFeatureBasedAlgorithm
30+
{
31+
public:
32+
33+
QgsDensifyGeometriesByIntervalAlgorithm() = default;
34+
QString name() const override;
35+
QString displayName() const override;
36+
QStringList tags() const override;
37+
QString group() const override;
38+
QString groupId() const override;
39+
QString shortHelpString() const override;
40+
QString shortDescription() const override;
41+
QgsDensifyGeometriesByIntervalAlgorithm *createInstance() const override SIP_FACTORY;
42+
QList<int> inputLayerTypes() const override;
43+
44+
protected:
45+
void initParameters( const QVariantMap &configuration = QVariantMap() ) override;
46+
QString outputName() const override;
47+
QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
48+
bool prepareAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
49+
50+
private:
51+
double mInterval = 0.0;
52+
bool mDynamicInterval = false;
53+
QgsProperty mIntervalProperty;
54+
};
55+
56+
///@endcond PRIVATE
57+
#endif // QGSALGORITHMDENSIFYGEOMETRIES_H

‎src/analysis/processing/qgsnativealgorithms.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "qgsalgorithmclip.h"
2828
#include "qgsalgorithmconvexhull.h"
2929
#include "qgsalgorithmdbscanclustering.h"
30+
#include "qgsalgorithmdensifygeometriesbyinterval.h"
3031
#include "qgsalgorithmdifference.h"
3132
#include "qgsalgorithmdissolve.h"
3233
#include "qgsalgorithmdrape.h"
@@ -246,6 +247,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
246247
addAlgorithm( new QgsWedgeBuffersAlgorithm() );
247248
addAlgorithm( new QgsZonalHistogramAlgorithm() );
248249
addAlgorithm( new QgsPolygonsToLinesAlgorithm() );
250+
addAlgorithm( new QgsDensifyGeometriesByIntervalAlgorithm() );
249251
}
250252

251253

‎tests/src/analysis/testqgsprocessingalgs.cpp

Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class TestQgsProcessingAlgs: public QObject
4242
*/
4343
std::unique_ptr<QgsProcessingFeatureBasedAlgorithm> featureBasedAlg( const QString &id );
4444

45-
QgsFeature runForFeature( const std::unique_ptr<QgsProcessingFeatureBasedAlgorithm> &alg, QgsFeature feature, const QString &layerType );
45+
QgsFeature runForFeature( const std::unique_ptr<QgsProcessingFeatureBasedAlgorithm> &alg, QgsFeature feature, const QString &layerType, QVariantMap parameters = QVariantMap() );
4646

4747
private slots:
4848
void initTestCase();// will be called before the first testfunction is executed.
@@ -58,9 +58,13 @@ class TestQgsProcessingAlgs: public QObject
5858
void kmeansCluster();
5959
void categorizeByStyle();
6060
void extractBinary();
61+
6162
void polygonsToLines_data();
6263
void polygonsToLines();
6364

65+
void densifyGeometries_data();
66+
void densifyGeometries();
67+
6468
private:
6569

6670
QString mPointLayerPath;
@@ -74,17 +78,16 @@ std::unique_ptr<QgsProcessingFeatureBasedAlgorithm> TestQgsProcessingAlgs::featu
7478
return std::unique_ptr<QgsProcessingFeatureBasedAlgorithm>( static_cast<QgsProcessingFeatureBasedAlgorithm *>( QgsApplication::processingRegistry()->createAlgorithmById( id ) ) );
7579
}
7680

77-
QgsFeature TestQgsProcessingAlgs::runForFeature( const std::unique_ptr< QgsProcessingFeatureBasedAlgorithm > &alg, QgsFeature feature, const QString &layerType )
81+
QgsFeature TestQgsProcessingAlgs::runForFeature( const std::unique_ptr< QgsProcessingFeatureBasedAlgorithm > &alg, QgsFeature feature, const QString &layerType, QVariantMap parameters )
7882
{
83+
Q_ASSERT( alg.get() );
7984
std::unique_ptr< QgsProcessingContext > context = qgis::make_unique< QgsProcessingContext >();
8085
QgsProject p;
8186
context->setProject( &p );
8287

8388
QgsProcessingFeedback feedback;
8489
context->setFeedback( &feedback );
8590

86-
QVariantMap parameters;
87-
8891
std::unique_ptr<QgsVectorLayer> inputLayer( qgis::make_unique<QgsVectorLayer>( layerType, QStringLiteral( "layer" ), QStringLiteral( "memory" ) ) );
8992
inputLayer->dataProvider()->addFeature( feature );
9093

@@ -753,5 +756,90 @@ void TestQgsProcessingAlgs::polygonsToLines()
753756
QVERIFY2( result.geometry().equals( expectedGeometry ), QStringLiteral( "Result: %1, Expected: %2" ).arg( result.geometry().asWkt(), expectedGeometry.asWkt() ).toUtf8().constData() );
754757
}
755758

759+
void TestQgsProcessingAlgs::densifyGeometries_data()
760+
{
761+
QTest::addColumn<QgsGeometry>( "sourceGeometry" );
762+
QTest::addColumn<QgsGeometry>( "expectedGeometry" );
763+
QTest::addColumn<double>( "interval" );
764+
QTest::addColumn<QString>( "geometryType" );
765+
766+
QTest::newRow( "Null geometry" )
767+
<< QgsGeometry()
768+
<< QgsGeometry()
769+
<< 0.1
770+
<< "Point";
771+
772+
QTest::newRow( "PointZ" )
773+
<< QgsGeometry::fromWkt( "PointZ( 1 2 3 )" )
774+
<< QgsGeometry::fromWkt( "PointZ( 1 2 3 )" )
775+
<< 0.1
776+
<< "Point";
777+
778+
QTest::newRow( "MultiPoint" )
779+
<< QgsGeometry::fromWkt( "MULTIPOINT ((155 271), (150 360), (260 360), (271 265), (280 260), (270 370), (154 354), (150 260))" )
780+
<< QgsGeometry::fromWkt( "MULTIPOINT ((155 271), (150 360), (260 360), (271 265), (280 260), (270 370), (154 354), (150 260))" )
781+
<< 0.1
782+
<< "Point";
783+
784+
QTest::newRow( "LineString big distance" )
785+
<< QgsGeometry::fromWkt( "LineString( 0 0, 10 0, 10 10 )" )
786+
<< QgsGeometry::fromWkt( "LineString( 0 0, 10 0, 10 10 )" )
787+
<< 100.
788+
<< "LineString";
789+
790+
QTest::newRow( "LineString small distance" )
791+
<< QgsGeometry::fromWkt( "LineString( 0 0, 10 0, 10 10 )" )
792+
<< QgsGeometry::fromWkt( "LineString (0 0, 2.5 0, 5 0, 7.5 0, 10 0, 10 2.5, 10 5, 10 7.5, 10 10)" )
793+
<< 3.
794+
<< "LineString";
795+
796+
QTest::newRow( "LineStringZ" )
797+
<< QgsGeometry::fromWkt( "LineStringZ( 0 0 1, 10 0 2, 10 10 0)" )
798+
<< QgsGeometry::fromWkt( "LineStringZ (0 0 1, 5 0 1.5, 10 0 2, 10 5 1, 10 10 0)" )
799+
<< 6.
800+
<< "LineString";
801+
802+
QTest::newRow( "LineStringM" )
803+
<< QgsGeometry::fromWkt( "LineStringM( 0 0 0, 10 0 2, 10 10 0)" )
804+
<< QgsGeometry::fromWkt( "LineStringM (0 0 0, 2.5 0 0.5, 5 0 1, 7.5 0 1.5, 10 0 2, 10 2.5 1.5, 10 5 1, 10 7.5 0.5, 10 10 0)" )
805+
<< 3.
806+
<< "LineString";
807+
808+
QTest::newRow( "LineStringZM" )
809+
<< QgsGeometry::fromWkt( "LineStringZM( 0 0 1 10, 10 0 2 8, 10 10 0 4)" )
810+
<< QgsGeometry::fromWkt( "LineStringZM (0 0 1 10, 5 0 1.5 9, 10 0 2 8, 10 5 1 6, 10 10 0 4)" )
811+
<< 6.
812+
<< "LineString";
813+
814+
QTest::newRow( "Polygon" )
815+
<< QgsGeometry::fromWkt( "Polygon(( 0 0, 20 0, 20 20, 0 0 ))" )
816+
<< QgsGeometry::fromWkt( "Polygon ((0 0, 5 0, 10 0, 15 0, 20 0, 20 5, 20 10, 20 15, 20 20, 16 16, 12 12, 7.99999999999999822 7.99999999999999822, 4 4, 0 0))" )
817+
<< 6.
818+
<< "Polygon";
819+
}
820+
821+
void TestQgsProcessingAlgs::densifyGeometries()
822+
{
823+
QFETCH( QgsGeometry, sourceGeometry );
824+
QFETCH( QgsGeometry, expectedGeometry );
825+
QFETCH( double, interval );
826+
QFETCH( QString, geometryType );
827+
828+
std::unique_ptr< QgsProcessingFeatureBasedAlgorithm > alg( featureBasedAlg( "native:densifygeometriesgivenaninterval" ) );
829+
830+
QVariantMap parameters;
831+
parameters.insert( QStringLiteral( "INTERVAL" ), interval );
832+
833+
QgsFeature feature;
834+
feature.setGeometry( sourceGeometry );
835+
836+
QgsFeature result = runForFeature( alg, feature, geometryType, parameters );
837+
838+
if ( expectedGeometry.isNull() )
839+
QVERIFY( result.geometry().isNull() );
840+
else
841+
QVERIFY2( result.geometry().equals( expectedGeometry ), QStringLiteral( "Result: %1, Expected: %2" ).arg( result.geometry().asWkt(), expectedGeometry.asWkt() ).toUtf8().constData() );
842+
}
843+
756844
QGSTEST_MAIN( TestQgsProcessingAlgs )
757845
#include "testqgsprocessingalgs.moc"

0 commit comments

Comments
 (0)
Please sign in to comment.