Skip to content

Commit 3c8d50d

Browse files
authoredNov 13, 2017
Merge pull request #5612 from nirvn/native_nodes
Optimize extract nodes algorithm
2 parents 6dbdbea + b7d0582 commit 3c8d50d

File tree

8 files changed

+223
-124
lines changed

8 files changed

+223
-124
lines changed
 

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

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

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ def name(self):
6666
def displayName(self):
6767
return self.tr('Extract specific nodes')
6868

69+
def tags(self):
70+
return self.tr('points,vertex,vertices').split(',')
71+
6972
def processAlgorithm(self, parameters, context, feedback):
7073
source = self.parameterAsSource(parameters, self.INPUT, context)
7174
fields = source.fields()

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@
6464
from .ExportGeometryInfo import ExportGeometryInfo
6565
from .ExtendLines import ExtendLines
6666
from .ExtentFromLayer import ExtentFromLayer
67-
from .ExtractNodes import ExtractNodes
6867
from .ExtractSpecificNodes import ExtractSpecificNodes
6968
from .FieldPyculator import FieldsPyculator
7069
from .FieldsCalculator import FieldsCalculator
@@ -190,7 +189,6 @@ def getAlgs(self):
190189
ExportGeometryInfo(),
191190
ExtendLines(),
192191
ExtentFromLayer(),
193-
ExtractNodes(),
194192
ExtractSpecificNodes(),
195193
FieldsCalculator(),
196194
FieldsMapper(),

‎python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,12 @@ tests:
11641164
OUTPUT:
11651165
name: expected/extract_nodes_multipolys.gml
11661166
type: vector
1167+
compare:
1168+
fields:
1169+
distance:
1170+
precision: 7
1171+
angle:
1172+
precision: 7
11671173

11681174
- algorithm: qgis:extractnodes
11691175
name: Extract nodes from polygons
@@ -1175,6 +1181,12 @@ tests:
11751181
OUTPUT:
11761182
name: expected/extract_nodes_polys.gml
11771183
type: vector
1184+
compare:
1185+
fields:
1186+
distance:
1187+
precision: 7
1188+
angle:
1189+
precision: 7
11781190

11791191
- algorithm: qgis:extractnodes
11801192
name: Extract nodes from multilines
@@ -1186,6 +1198,12 @@ tests:
11861198
OUTPUT:
11871199
name: expected/extract_nodes_multilines.gml
11881200
type: vector
1201+
compare:
1202+
fields:
1203+
distance:
1204+
precision: 7
1205+
angle:
1206+
precision: 7
11891207

11901208
- algorithm: qgis:extractnodes
11911209
name: Extract nodes from lines
@@ -1197,6 +1215,12 @@ tests:
11971215
OUTPUT:
11981216
name: expected/extract_nodes_lines.gml
11991217
type: vector
1218+
compare:
1219+
fields:
1220+
distance:
1221+
precision: 7
1222+
angle:
1223+
precision: 7
12001224

12011225
- algorithm: native:simplifygeometries
12021226
name: Simplify (lines)

‎src/analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ SET(QGIS_ANALYSIS_SRCS
3535
processing/qgsalgorithmextractbyexpression.cpp
3636
processing/qgsalgorithmextractbyextent.cpp
3737
processing/qgsalgorithmextractbylocation.cpp
38+
processing/qgsalgorithmextractnodes.cpp
3839
processing/qgsalgorithmfiledownloader.cpp
3940
processing/qgsalgorithmfixgeometries.cpp
4041
processing/qgsalgorithmjoinbyattribute.cpp
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/***************************************************************************
2+
qgsalgorithmextractnodes.cpp
3+
--------------------------
4+
begin : November 2017
5+
copyright : (C) 2017 by Mathieu Pellerin
6+
email : nirvn dot asia at gmail dot com
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+
#include "qgsalgorithmextractnodes.h"
19+
20+
#include "qgsabstractgeometry.h"
21+
#include "qgsgeometryutils.h"
22+
23+
///@cond PRIVATE
24+
25+
QString QgsExtractNodesAlgorithm::name() const
26+
{
27+
return QStringLiteral( "extractnodes" );
28+
}
29+
30+
QString QgsExtractNodesAlgorithm::displayName() const
31+
{
32+
return QObject::tr( "Extract nodes" );
33+
}
34+
35+
QStringList QgsExtractNodesAlgorithm::tags() const
36+
{
37+
return QObject::tr( "points,vertex,vertices" ).split( ',' );
38+
}
39+
40+
QString QgsExtractNodesAlgorithm::group() const
41+
{
42+
return QObject::tr( "Vector geometry" );
43+
}
44+
45+
QString QgsExtractNodesAlgorithm::shortHelpString() const
46+
{
47+
return QObject::tr( "This algorithm takes a line or polygon layer and generates a point layer with points representing the nodes in the input lines or polygons. The attributes associated to each point are the same ones associated to the line or polygon that the point belongs to." ) +
48+
QStringLiteral( "\n\n" ) +
49+
QObject::tr( "Additional fields are added to the nodes indicating the node index (beginning at 0), distance along original geometry and bisector angle of node for original geometry." );
50+
}
51+
52+
QgsExtractNodesAlgorithm *QgsExtractNodesAlgorithm::createInstance() const
53+
{
54+
return new QgsExtractNodesAlgorithm();
55+
}
56+
57+
void QgsExtractNodesAlgorithm::initAlgorithm( const QVariantMap & )
58+
{
59+
addParameter( new QgsProcessingParameterFeatureSource( QStringLiteral( "INPUT" ), QObject::tr( "Input layer" ) ) );
60+
61+
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Nodes" ) ) );
62+
}
63+
64+
QVariantMap QgsExtractNodesAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
65+
{
66+
std::unique_ptr< QgsFeatureSource > featureSource( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
67+
if ( !featureSource )
68+
return QVariantMap();
69+
70+
QgsWkbTypes::Type outputWkbType = QgsWkbTypes::Point;
71+
if ( QgsWkbTypes::hasM( featureSource->wkbType() ) )
72+
{
73+
outputWkbType = QgsWkbTypes::addM( outputWkbType );
74+
}
75+
if ( QgsWkbTypes::hasZ( featureSource->wkbType() ) )
76+
{
77+
outputWkbType = QgsWkbTypes::addZ( outputWkbType );
78+
}
79+
80+
QgsFields outputFields = featureSource->fields();
81+
outputFields.append( QgsField( QStringLiteral( "node_index" ), QVariant::Int, QString(), 10, 0 ) );
82+
outputFields.append( QgsField( QStringLiteral( "distance" ), QVariant::Double, QString(), 20, 14 ) );
83+
outputFields.append( QgsField( QStringLiteral( "angle" ), QVariant::Double, QString(), 20, 14 ) );
84+
85+
QString dest;
86+
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest, outputFields, outputWkbType, featureSource->sourceCrs() ) );
87+
if ( !sink )
88+
return QVariantMap();
89+
90+
double step = featureSource->featureCount() > 0 ? 100.0 / featureSource->featureCount() : 1;
91+
QgsFeatureIterator fi = featureSource->getFeatures( QgsFeatureRequest() );
92+
QgsFeature f;
93+
int i = -1;
94+
while ( fi.nextFeature( f ) )
95+
{
96+
i++;
97+
if ( feedback->isCanceled() )
98+
{
99+
break;
100+
}
101+
102+
QgsGeometry inputGeom = f.geometry();
103+
if ( inputGeom.isNull() )
104+
{
105+
sink->addFeature( f, QgsFeatureSink::FastInsert );
106+
}
107+
else
108+
{
109+
QgsAbstractGeometry::vertex_iterator vi = inputGeom.constGet()->vertices_begin();
110+
QgsPoint vertex;
111+
int vertexPos = 0;
112+
while ( vi != inputGeom.constGet()->vertices_end() )
113+
{
114+
QgsVertexId vertexId = vi.vertexId();
115+
double distance = QgsGeometryUtils::distanceToVertex( *( inputGeom.constGet() ), vertexId );
116+
double angle = inputGeom.constGet()->vertexAngle( vertexId ) * 180 / M_PI;
117+
QgsAttributes attrs = f.attributes();
118+
attrs << vertexPos
119+
<< distance
120+
<< angle;
121+
QgsFeature outputFeature = QgsFeature();
122+
outputFeature.setAttributes( attrs );
123+
outputFeature.setGeometry( QgsGeometry( ( *vi ).clone() ) );
124+
sink->addFeature( outputFeature, QgsFeatureSink::FastInsert );
125+
vi++;
126+
vertexPos++;
127+
}
128+
}
129+
feedback->setProgress( i * step );
130+
}
131+
132+
QVariantMap outputs;
133+
outputs.insert( QStringLiteral( "OUTPUT" ), dest );
134+
return outputs;
135+
}
136+
137+
///@endcond
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/***************************************************************************
2+
qgsalgorithmextractnodes.h
3+
-------------------------
4+
begin : November 2017
5+
copyright : (C) 2017 by Mathieu Pellerin
6+
email : nirvn dot asia at gmail dot com
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 QGSALGORITHMEXTRACTNODES_H
19+
#define QGSALGORITHMEXTRACTNODES_H
20+
21+
#define SIP_NO_FILE
22+
23+
#include "qgis.h"
24+
#include "qgsprocessingalgorithm.h"
25+
26+
///@cond PRIVATE
27+
28+
/**
29+
* Native extract nodes algorithm.
30+
*/
31+
class QgsExtractNodesAlgorithm : public QgsProcessingAlgorithm
32+
{
33+
34+
public:
35+
36+
QgsExtractNodesAlgorithm() = default;
37+
void initAlgorithm( const QVariantMap &configuration = QVariantMap() ) override;
38+
QString name() const override;
39+
QString displayName() const override;
40+
virtual QStringList tags() const override;
41+
QString group() const override;
42+
QString shortHelpString() const override;
43+
QgsExtractNodesAlgorithm *createInstance() const override SIP_FACTORY;
44+
45+
protected:
46+
47+
virtual QVariantMap processAlgorithm( const QVariantMap &parameters,
48+
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
49+
50+
};
51+
52+
///@endcond PRIVATE
53+
54+
#endif // QGSALGORITHMEXTRACTNODES_H
55+
56+

‎src/analysis/processing/qgsnativealgorithms.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "qgsalgorithmextractbyexpression.h"
3333
#include "qgsalgorithmextractbyextent.h"
3434
#include "qgsalgorithmextractbylocation.h"
35+
#include "qgsalgorithmextractnodes.h"
3536
#include "qgsalgorithmfiledownloader.h"
3637
#include "qgsalgorithmfixgeometries.h"
3738
#include "qgsalgorithmjoinbyattribute.h"
@@ -106,6 +107,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
106107
addAlgorithm( new QgsExtractByExpressionAlgorithm() );
107108
addAlgorithm( new QgsExtractByExtentAlgorithm() );
108109
addAlgorithm( new QgsExtractByLocationAlgorithm() );
110+
addAlgorithm( new QgsExtractNodesAlgorithm() );
109111
addAlgorithm( new QgsFileDownloaderAlgorithm() );
110112
addAlgorithm( new QgsFixGeometriesAlgorithm() );
111113
addAlgorithm( new QgsJoinByAttributeAlgorithm() );

0 commit comments

Comments
 (0)
Please sign in to comment.