QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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:156
Base class for providing feedback from a processing algorithm.
bool isMultipart() const
Returns true if WKB of the geometry is of WKBMulti* type.
QList< QgsFeature > QgsFeatureList
Definition: qgsfeature.h:571
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:122
void setAttributes(const QgsAttributes &attrs)
Sets the feature&#39;s attributes.
Definition: qgsfeature.cpp:127
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
Definition: qgsfeature.h:55
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:197
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.
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
Geometry collection.
T qgsgeometry_cast(const QgsAbstractGeometry *geom)
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
int nCurves() const
Returns the number of curves in the geometry.
QVector< QgsPoint > QgsPointSequence
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:43
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
Vector line layers.
Definition: qgsprocessing.h:49
const QgsCurve * curveAt(int i) const
Returns the curve at the specified index.
QgsPoint pointN(int i) const
Returns the specified point from inside the line string.
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:576
Contains information about the context in which a processing algorithm is executed.
QgsAttributes attributes
Definition: qgsfeature.h:65