QGIS API Documentation  3.2.0-Bonn (bc43194)
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 std::vector<QgsGeometry> QgsExplodeAlgorithm::extractAsParts( const QgsGeometry &geometry ) const
109 {
110  if ( geometry.isMultipart() )
111  {
112  std::vector<QgsGeometry> parts;
113  const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection * >( geometry.constGet() );
114  for ( int part = 0; part < collection->numGeometries(); ++part )
115  {
116  std::vector<QgsGeometry> segments = curveAsSingleSegments( qgsgeometry_cast< const QgsCurve * >( collection->geometryN( part ) ) );
117  parts.reserve( parts.size() + segments.size() );
118  std::move( std::begin( segments ), std::end( segments ), std::back_inserter( parts ) );
119  }
120  return parts;
121  }
122  else
123  {
124  return curveAsSingleSegments( qgsgeometry_cast< const QgsCurve * >( geometry.constGet() ) );
125  }
126 }
127 
128 std::vector<QgsGeometry> QgsExplodeAlgorithm::curveAsSingleSegments( const QgsCurve *curve, bool useCompoundCurves ) const
129 {
130  std::vector<QgsGeometry> parts;
131  if ( !curve )
132  return parts;
133  switch ( QgsWkbTypes::flatType( curve->wkbType() ) )
134  {
136  {
137  const QgsLineString *line = qgsgeometry_cast< const QgsLineString * >( curve );
138  for ( int i = 0; i < line->numPoints() - 1; ++i )
139  {
140  QgsPoint ptA = line->pointN( i );
141  QgsPoint ptB = line->pointN( i + 1 );
142  std::unique_ptr< QgsLineString > ls = qgis::make_unique< QgsLineString >( QVector< QgsPoint >() << ptA << ptB );
143  if ( !useCompoundCurves )
144  {
145  parts.emplace_back( QgsGeometry( std::move( ls ) ) );
146  }
147  else
148  {
149  std::unique_ptr< QgsCompoundCurve > cc = qgis::make_unique< QgsCompoundCurve >();
150  cc->addCurve( ls.release() );
151  parts.emplace_back( QgsGeometry( std::move( cc ) ) );
152  }
153  }
154  break;
155  }
156 
158  {
159  const QgsCircularString *string = qgsgeometry_cast< const QgsCircularString * >( curve );
160  for ( int i = 0; i < string->numPoints() - 2; i += 2 )
161  {
162  QgsPoint ptA = string->pointN( i );
163  QgsPoint ptB = string->pointN( i + 1 );
164  QgsPoint ptC = string->pointN( i + 2 );
165  std::unique_ptr< QgsCircularString > cs = qgis::make_unique< QgsCircularString >();
166  cs->setPoints( QgsPointSequence() << ptA << ptB << ptC );
167  if ( !useCompoundCurves )
168  {
169  parts.emplace_back( QgsGeometry( std::move( cs ) ) );
170  }
171  else
172  {
173  std::unique_ptr< QgsCompoundCurve > cc = qgis::make_unique< QgsCompoundCurve >();
174  cc->addCurve( cs.release() );
175  parts.emplace_back( QgsGeometry( std::move( cc ) ) );
176  }
177  }
178  break;
179  }
180 
182  {
183  const QgsCompoundCurve *compoundCurve = qgsgeometry_cast< QgsCompoundCurve * >( curve );
184  for ( int i = 0; i < compoundCurve->nCurves(); ++i )
185  {
186  std::vector<QgsGeometry> segments = curveAsSingleSegments( compoundCurve->curveAt( i ), true );
187  parts.reserve( parts.size() + segments.size() );
188  std::move( std::begin( segments ), std::end( segments ), std::back_inserter( parts ) );
189  }
190  break;
191  }
192 
193  default:
194  break;
195 
196  }
197  return parts;
198 }
199 
201 
202 
203 
static Type singleType(Type type)
Returns the single type for a WKB type.
Definition: qgswkbtypes.h:152
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:549
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:104
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:62
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Definition: qgsfeature.cpp:190
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:67
Geometry collection.
T qgsgeometry_cast(const QgsAbstractGeometry *geom)
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
QgsGeometry geometry() const
Returns the geometry associated with this feature.
Definition: qgsfeature.cpp:101
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.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:427
Contains information about the context in which a processing algorithm is executed.
QgsAttributes attributes
Definition: qgsfeature.h:72