1 /***************************************************************************
2                          qgsalgorithmpolygonstolines.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 #include "qgsalgorithmpolygonstolines.h"
19 #include "qgsgeometrycollection.h"
20 #include "qgscurvepolygon.h"
21 #include "qgscurve.h"
22 #include "qgsmultilinestring.h"
23 
24 ///@cond PRIVATE
25 
name() const26 QString QgsPolygonsToLinesAlgorithm::name() const
27 {
28   return QStringLiteral( "polygonstolines" );
29 }
30 
displayName() const31 QString QgsPolygonsToLinesAlgorithm::displayName() const
32 {
33   return QObject::tr( "Polygons to lines" );
34 }
35 
tags() const36 QStringList QgsPolygonsToLinesAlgorithm::tags() const
37 {
38   return QObject::tr( "line,polygon,convert" ).split( ',' );
39 }
40 
group() const41 QString QgsPolygonsToLinesAlgorithm::group() const
42 {
43   return QObject::tr( "Vector geometry" );
44 }
45 
groupId() const46 QString QgsPolygonsToLinesAlgorithm::groupId() const
47 {
48   return QStringLiteral( "vectorgeometry" );
49 }
50 
outputName() const51 QString QgsPolygonsToLinesAlgorithm::outputName() const
52 {
53   return QObject::tr( "Lines" );
54 }
55 
outputLayerType() const56 QgsProcessing::SourceType QgsPolygonsToLinesAlgorithm::outputLayerType() const
57 {
58   return QgsProcessing::TypeVectorLine;
59 }
60 
outputWkbType(QgsWkbTypes::Type inputWkbType) const61 QgsWkbTypes::Type QgsPolygonsToLinesAlgorithm::outputWkbType( QgsWkbTypes::Type inputWkbType ) const
62 {
63   QgsWkbTypes::Type wkbType = QgsWkbTypes::Unknown;
64 
65   if ( QgsWkbTypes::singleType( QgsWkbTypes::flatType( inputWkbType ) ) == QgsWkbTypes::Polygon )
66     wkbType = QgsWkbTypes::MultiLineString;
67   else if ( QgsWkbTypes::singleType( QgsWkbTypes::flatType( inputWkbType ) ) == QgsWkbTypes::CurvePolygon )
68     wkbType = QgsWkbTypes::MultiCurve;
69 
70   if ( QgsWkbTypes::hasM( inputWkbType ) )
71     wkbType = QgsWkbTypes::addM( wkbType );
72   if ( QgsWkbTypes::hasZ( inputWkbType ) )
73     wkbType = QgsWkbTypes::addZ( wkbType );
74 
75   return wkbType;
76 }
77 
shortHelpString() const78 QString QgsPolygonsToLinesAlgorithm::shortHelpString() const
79 {
80   return QObject::tr( "Converts polygons to lines" );
81 }
82 
shortDescription() const83 QString QgsPolygonsToLinesAlgorithm::shortDescription() const
84 {
85   return QObject::tr( "Converts polygons to lines." );
86 }
87 
createInstance() const88 QgsPolygonsToLinesAlgorithm *QgsPolygonsToLinesAlgorithm::createInstance() const
89 {
90   return new QgsPolygonsToLinesAlgorithm();
91 }
92 
inputLayerTypes() const93 QList<int> QgsPolygonsToLinesAlgorithm::inputLayerTypes() const
94 {
95   return QList<int>() << QgsProcessing::TypeVectorPolygon;
96 }
97 
processFeature(const QgsFeature & feature,QgsProcessingContext & context,QgsProcessingFeedback *)98 QgsFeatureList QgsPolygonsToLinesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback * )
99 {
100   Q_UNUSED( context )
101 
102   QgsFeatureList result;
103   QgsFeature feat = feature;
104   if ( feat.hasGeometry() )
105     feat.setGeometry( convertToLines( feat.geometry() ) );
106 
107   result << feat;
108   return result;
109 }
110 
convertToLines(const QgsGeometry & geometry) const111 QgsGeometry QgsPolygonsToLinesAlgorithm::convertToLines( const QgsGeometry &geometry ) const
112 {
113   auto rings = extractRings( geometry.constGet() );
114 
115   QgsWkbTypes::Type resultType = outputWkbType( geometry.wkbType() );
116 
117   std::unique_ptr<QgsMultiCurve> lineGeometry;
118 
119   if ( QgsWkbTypes::flatType( resultType ) == QgsWkbTypes::MultiLineString )
120     lineGeometry = std::make_unique<QgsMultiLineString>();
121   else
122     lineGeometry = std::make_unique<QgsMultiCurve>();
123 
124   lineGeometry->reserve( rings.size() );
125   for ( auto ring : std::as_const( rings ) )
126     lineGeometry->addGeometry( ring );
127 
128   return QgsGeometry( lineGeometry.release() );
129 }
130 
extractRings(const QgsAbstractGeometry * geom) const131 QList<QgsCurve *> QgsPolygonsToLinesAlgorithm::extractRings( const QgsAbstractGeometry *geom ) const
132 {
133   QList<QgsCurve *> rings;
134 
135   if ( QgsGeometryCollection *collection = qgsgeometry_cast<QgsGeometryCollection *>( geom ) )
136   {
137     QgsGeometryPartIterator parts = collection->parts();
138     while ( parts.hasNext() )
139       rings.append( extractRings( parts.next() ) );
140   }
141   else if ( QgsCurvePolygon *polygon = qgsgeometry_cast<QgsCurvePolygon *>( geom ) )
142   {
143     if ( auto exteriorRing = polygon->exteriorRing() )
144       rings.append( exteriorRing->clone() );
145     for ( int i = 0; i < polygon->numInteriorRings(); ++i )
146     {
147       rings.append( polygon->interiorRing( i )->clone() );
148     }
149   }
150 
151   return rings;
152 }
153 
154 
155 
156 ///@endcond
157 
158 
159