QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgsalgorithmexplode.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsalgorithmexplode.cpp
3  ---------------------
4  begin : April 2018
5  copyright : (C) 2018 by Nyall Dawson
6  email : nyall dot dawson 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 "qgsalgorithmexplode.h"
19 #include "qgscurve.h"
20 #include "qgslinestring.h"
21 #include "qgscircularstring.h"
22 #include "qgscompoundcurve.h"
23 #include "qgsgeometrycollection.h"
24 
26 
27 QString QgsExplodeAlgorithm::name() const
28 {
29  return QStringLiteral( "explodelines" );
30 }
31 
32 QString QgsExplodeAlgorithm::displayName() const
33 {
34  return QObject::tr( "Explode lines" );
35 }
36 
37 QStringList QgsExplodeAlgorithm::tags() const
38 {
39  return QObject::tr( "segments,parts" ).split( ',' );
40 }
41 
42 QString QgsExplodeAlgorithm::group() const
43 {
44  return QObject::tr( "Vector geometry" );
45 }
46 
47 QString QgsExplodeAlgorithm::groupId() const
48 {
49  return QStringLiteral( "vectorgeometry" );
50 }
51 
52 QString QgsExplodeAlgorithm::shortHelpString() const
53 {
54  return QObject::tr( "This algorithm takes a lines layer and creates a new one in which each line is replaced by a set of "
55  "lines representing the segments in the original line. Each line in the resulting layer contains only a "
56  "start and an end point, with no intermediate nodes between them.\n\n"
57  "If the input layer consists of CircularStrings or CompoundCurves, the output layer will be of the "
58  "same type and contain only single curve segments." );
59 }
60 
61 QList<int> QgsExplodeAlgorithm::inputLayerTypes() const
62 {
63  return QList<int>() << QgsProcessing::TypeVectorLine;
64 }
65 
66 QgsProcessing::SourceType QgsExplodeAlgorithm::outputLayerType() const
67 {
69 }
70 
71 QgsExplodeAlgorithm *QgsExplodeAlgorithm::createInstance() const
72 {
73  return new QgsExplodeAlgorithm();
74 }
75 
76 QString QgsExplodeAlgorithm::outputName() const
77 {
78  return QObject::tr( "Exploded" );
79 }
80 
81 QgsWkbTypes::Type QgsExplodeAlgorithm::outputWkbType( QgsWkbTypes::Type inputWkbType ) const
82 {
83  return QgsWkbTypes::singleType( inputWkbType );
84 }
85 
86 QgsFeatureList QgsExplodeAlgorithm::processFeature( const QgsFeature &f, QgsProcessingContext &, QgsProcessingFeedback * )
87 {
88  if ( !f.hasGeometry() )
89  {
90  return QgsFeatureList() << f;
91  }
92  else
93  {
94  const std::vector<QgsGeometry> parts = extractAsParts( f.geometry() );
95  QgsFeature outputFeature;
96  QgsFeatureList features;
97  features.reserve( parts.size() );
98  for ( const QgsGeometry &part : parts )
99  {
100  outputFeature.setAttributes( f.attributes() );
101  outputFeature.setGeometry( part );
102  features << outputFeature;
103  }
104  return features;
105  }
106 }
107 
108 QgsFeatureSink::SinkFlags QgsExplodeAlgorithm::sinkFlags() const
109 {
111 }
112 
113 std::vector<QgsGeometry> QgsExplodeAlgorithm::extractAsParts( const QgsGeometry &geometry ) const
114 {
115  if ( geometry.isMultipart() )
116  {
117  std::vector<QgsGeometry> parts;
118  const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( geometry.constGet() );
119  for ( int part = 0; part < collection->numGeometries(); ++part )
120  {
121  std::vector<QgsGeometry> segments = curveAsSingleSegments( qgsgeometry_cast< const QgsCurve * >( collection->geometryN( part ) ) );
122  parts.reserve( parts.size() + segments.size() );
123  std::move( std::begin( segments ), std::end( segments ), std::back_inserter( parts ) );
124  }
125  return parts;
126  }
127  else
128  {
129  return curveAsSingleSegments( qgsgeometry_cast< const QgsCurve * >( geometry.constGet() ) );
130  }
131 }
132 
133 std::vector<QgsGeometry> QgsExplodeAlgorithm::curveAsSingleSegments( const QgsCurve *curve, bool useCompoundCurves ) const
134 {
135  std::vector<QgsGeometry> parts;
136  if ( !curve )
137  return parts;
138  switch ( QgsWkbTypes::flatType( curve->wkbType() ) )
139  {
141  {
142  const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( curve );
143  for ( int i = 0; i < line->numPoints() - 1; ++i )
144  {
145  QgsPoint ptA = line->pointN( i );
146  QgsPoint ptB = line->pointN( i + 1 );
147  std::unique_ptr< QgsLineString > ls = qgis::make_unique< QgsLineString >( QVector< QgsPoint >() << ptA << ptB );
148  if ( !useCompoundCurves )
149  {
150  parts.emplace_back( QgsGeometry( std::move( ls ) ) );
151  }
152  else
153  {
154  std::unique_ptr< QgsCompoundCurve > cc = qgis::make_unique< QgsCompoundCurve >();
155  cc->addCurve( ls.release() );
156  parts.emplace_back( QgsGeometry( std::move( cc ) ) );
157  }
158  }
159  break;
160  }
161 
163  {
164  const QgsCircularString *string = qgsgeometry_cast< const QgsCircularString * >( curve );
165  for ( int i = 0; i < string->numPoints() - 2; i += 2 )
166  {
167  QgsPoint ptA = string->pointN( i );
168  QgsPoint ptB = string->pointN( i + 1 );
169  QgsPoint ptC = string->pointN( i + 2 );
170  std::unique_ptr< QgsCircularString > cs = qgis::make_unique< QgsCircularString >();
171  cs->setPoints( QgsPointSequence() << ptA << ptB << ptC );
172  if ( !useCompoundCurves )
173  {
174  parts.emplace_back( QgsGeometry( std::move( cs ) ) );
175  }
176  else
177  {
178  std::unique_ptr< QgsCompoundCurve > cc = qgis::make_unique< QgsCompoundCurve >();
179  cc->addCurve( cs.release() );
180  parts.emplace_back( QgsGeometry( std::move( cc ) ) );
181  }
182  }
183  break;
184  }
185 
187  {
188  const QgsCompoundCurve *compoundCurve = qgsgeometry_cast< QgsCompoundCurve * >( curve );
189  for ( int i = 0; i < compoundCurve->nCurves(); ++i )
190  {
191  std::vector<QgsGeometry> segments = curveAsSingleSegments( compoundCurve->curveAt( i ), true );
192  parts.reserve( parts.size() + segments.size() );
193  std::move( std::begin( segments ), std::end( segments ), std::back_inserter( parts ) );
194  }
195  break;
196  }
197 
198  default:
199  break;
200 
201  }
202  return parts;
203 }
204 
206 
207 
208 
static Type singleType(Type type)
Returns the single type for a WKB type.
Definition: qgswkbtypes.h:154
Base class for providing feedback from a processing algorithm.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:571
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:106
void setAttributes(const QgsAttributes &attrs)
Sets the feature&#39;s attributes.
Definition: qgsfeature.cpp:127
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
const QgsCurve * curveAt(int i) const
Returns the curve at the specified index.
This flag indicates, that a primary key field cannot be guaranteed to be unique and the sink should i...
int numPoints() const override
Returns the number of points in the curve.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
Geometry collection.
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
int nCurves() const
Returns the number of curves in the geometry.
T qgsgeometry_cast(const QgsAbstractGeometry *geom)
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
int numGeometries() const
Returns the number of geometries within the collection.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
QVector< QgsPoint > QgsPointSequence
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:43
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
Vector line layers.
Definition: qgsprocessing.h:49
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
SourceType
Data source types enum.
Definition: qgsprocessing.h:44
Compound curve geometry type.
Circular string geometry type.
QgsGeometry geometry
Definition: qgsfeature.h:67
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:565
Contains information about the context in which a processing algorithm is executed.
QgsAttributes attributes
Definition: qgsfeature.h:65