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() const26QString QgsPolygonsToLinesAlgorithm::name() const 27 { 28 return QStringLiteral( "polygonstolines" ); 29 } 30 displayName() const31QString QgsPolygonsToLinesAlgorithm::displayName() const 32 { 33 return QObject::tr( "Polygons to lines" ); 34 } 35 tags() const36QStringList QgsPolygonsToLinesAlgorithm::tags() const 37 { 38 return QObject::tr( "line,polygon,convert" ).split( ',' ); 39 } 40 group() const41QString QgsPolygonsToLinesAlgorithm::group() const 42 { 43 return QObject::tr( "Vector geometry" ); 44 } 45 groupId() const46QString QgsPolygonsToLinesAlgorithm::groupId() const 47 { 48 return QStringLiteral( "vectorgeometry" ); 49 } 50 outputName() const51QString QgsPolygonsToLinesAlgorithm::outputName() const 52 { 53 return QObject::tr( "Lines" ); 54 } 55 outputLayerType() const56QgsProcessing::SourceType QgsPolygonsToLinesAlgorithm::outputLayerType() const 57 { 58 return QgsProcessing::TypeVectorLine; 59 } 60 outputWkbType(QgsWkbTypes::Type inputWkbType) const61QgsWkbTypes::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() const78QString QgsPolygonsToLinesAlgorithm::shortHelpString() const 79 { 80 return QObject::tr( "Converts polygons to lines" ); 81 } 82 shortDescription() const83QString QgsPolygonsToLinesAlgorithm::shortDescription() const 84 { 85 return QObject::tr( "Converts polygons to lines." ); 86 } 87 createInstance() const88QgsPolygonsToLinesAlgorithm *QgsPolygonsToLinesAlgorithm::createInstance() const 89 { 90 return new QgsPolygonsToLinesAlgorithm(); 91 } 92 inputLayerTypes() const93QList<int> QgsPolygonsToLinesAlgorithm::inputLayerTypes() const 94 { 95 return QList<int>() << QgsProcessing::TypeVectorPolygon; 96 } 97 processFeature(const QgsFeature & feature,QgsProcessingContext & context,QgsProcessingFeedback *)98QgsFeatureList 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) const111QgsGeometry 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) const131QList<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