Add native polygonstolines algorithm

This commit is contained in:
Matthias Kuhn 2019-01-11 23:28:58 +01:00
parent 8709ab61eb
commit 4c8af20b51
No known key found for this signature in database
GPG Key ID: 7A7F1A1C90C3E6A7
6 changed files with 216 additions and 133 deletions

View File

@ -1,130 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
PolygonsToLines.py
---------------------
Date : August 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import os
from qgis.PyQt.QtGui import QIcon
from qgis.core import (QgsApplication,
QgsGeometry,
QgsGeometryCollection,
QgsMultiLineString,
QgsMultiCurve,
QgsWkbTypes,
QgsProcessing)
from processing.algs.qgis.QgisAlgorithm import QgisFeatureBasedAlgorithm
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
class PolygonsToLines(QgisFeatureBasedAlgorithm):
def icon(self):
return QgsApplication.getThemeIcon("/algorithms/mAlgorithmPolygonToLine.svg")
def svgIconPath(self):
return QgsApplication.iconPath("/algorithms/mAlgorithmPolygonToLine.svg")
def tags(self):
return self.tr('line,polygon,convert').split(',')
def group(self):
return self.tr('Vector geometry')
def groupId(self):
return 'vectorgeometry'
def __init__(self):
super().__init__()
def name(self):
return 'polygonstolines'
def displayName(self):
return self.tr('Polygons to lines')
def outputName(self):
return self.tr('Lines')
def outputType(self):
return QgsProcessing.TypeVectorLine
def inputLayerTypes(self):
return [QgsProcessing.TypeVectorPolygon]
def outputWkbType(self, input_wkb_type):
return self.convertWkbToLines(input_wkb_type)
def processFeature(self, feature, context, feedback):
if feature.hasGeometry():
feature.setGeometry(QgsGeometry(self.convertToLines(feature.geometry())))
return [feature]
def supportInPlaceEdit(self, layer):
return False
def convertWkbToLines(self, wkb):
multi_wkb = QgsWkbTypes.NoGeometry
if QgsWkbTypes.singleType(QgsWkbTypes.flatType(wkb)) == QgsWkbTypes.Polygon:
multi_wkb = QgsWkbTypes.MultiLineString
elif QgsWkbTypes.singleType(QgsWkbTypes.flatType(wkb)) == QgsWkbTypes.CurvePolygon:
multi_wkb = QgsWkbTypes.MultiCurve
if QgsWkbTypes.hasM(wkb):
multi_wkb = QgsWkbTypes.addM(multi_wkb)
if QgsWkbTypes.hasZ(wkb):
multi_wkb = QgsWkbTypes.addZ(multi_wkb)
return multi_wkb
def convertToLines(self, geometry):
rings = self.getRings(geometry.constGet())
output_wkb = self.convertWkbToLines(geometry.wkbType())
out_geom = None
if QgsWkbTypes.flatType(output_wkb) == QgsWkbTypes.MultiLineString:
out_geom = QgsMultiLineString()
else:
out_geom = QgsMultiCurve()
for ring in rings:
out_geom.addGeometry(ring)
return out_geom
def getRings(self, geometry):
rings = []
if isinstance(geometry, QgsGeometryCollection):
# collection
for i in range(geometry.numGeometries()):
rings.extend(self.getRings(geometry.geometryN(i)))
else:
# not collection
rings.append(geometry.exteriorRing().clone())
for i in range(geometry.numInteriorRings()):
rings.append(geometry.interiorRing(i).clone())
return rings

View File

@ -98,7 +98,6 @@ from .PointsLayerFromTable import PointsLayerFromTable
from .PointsToPaths import PointsToPaths
from .PoleOfInaccessibility import PoleOfInaccessibility
from .Polygonize import Polygonize
from .PolygonsToLines import PolygonsToLines
from .PostGISExecuteSQL import PostGISExecuteSQL
from .PostGISExecuteAndLoadSQL import PostGISExecuteAndLoadSQL
from .RandomExtract import RandomExtract
@ -210,7 +209,6 @@ class QgisAlgorithmProvider(QgsProcessingProvider):
PointsToPaths(),
PoleOfInaccessibility(),
Polygonize(),
PolygonsToLines(),
PostGISExecuteSQL(),
PostGISExecuteAndLoadSQL(),
RandomExtract(),

View File

@ -73,6 +73,7 @@ SET(QGIS_ANALYSIS_SRCS
processing/qgsalgorithmorientedminimumboundingbox.cpp
processing/qgsalgorithmpackage.cpp
processing/qgsalgorithmarrayoffsetlines.cpp
processing/qgsalgorithmpolygonstolines.cpp
processing/qgsalgorithmpointonsurface.cpp
processing/qgsalgorithmprojectpointcartesian.cpp
processing/qgsalgorithmpromotetomultipart.cpp

View File

@ -0,0 +1,150 @@
/***************************************************************************
qgsalgorithmpolygonstolines.cpp
---------------------
begin : January 2019
copyright : (C) 2019 by Matthias Kuhn
email : matthias@opengis.ch
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsalgorithmpolygonstolines.h"
#include "qgsgeometrycollection.h"
#include "qgscurvepolygon.h"
#include "qgscurve.h"
#include "qgsmultilinestring.h"
///@cond PRIVATE
QString QgsPolygonsToLinesAlgorithm::name() const
{
return QStringLiteral( "polygonstolines" );
}
QString QgsPolygonsToLinesAlgorithm::displayName() const
{
return QObject::tr( "Polygons to lines" );
}
QStringList QgsPolygonsToLinesAlgorithm::tags() const
{
return QObject::tr( "line,polygon,convert" ).split( ',' );
}
QString QgsPolygonsToLinesAlgorithm::group() const
{
return QObject::tr( "Vector creation" );
}
QString QgsPolygonsToLinesAlgorithm::groupId() const
{
return QStringLiteral( "vectorgeometry" );
}
QString QgsPolygonsToLinesAlgorithm::outputName() const
{
return QObject::tr( "Lines" );
}
QString QgsPolygonsToLinesAlgorithm::shortHelpString() const
{
return QObject::tr( "Converts polygons to lines" );
}
QString QgsPolygonsToLinesAlgorithm::shortDescription() const
{
return QObject::tr( "Converts polygons to lines." );
}
QgsPolygonsToLinesAlgorithm *QgsPolygonsToLinesAlgorithm::createInstance() const
{
return new QgsPolygonsToLinesAlgorithm();
}
QList<int> QgsPolygonsToLinesAlgorithm::inputLayerTypes() const
{
return QList< int >() << QgsProcessing::TypeVectorPolygon;
}
QgsFeatureList QgsPolygonsToLinesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback * )
{
QgsFeatureList result;
QgsFeature feat = feature;
if ( feat.hasGeometry() )
feat.setGeometry( convertToLines( feat.geometry() ) );
result << feat;
return result;
}
QgsGeometry QgsPolygonsToLinesAlgorithm::convertToLines( const QgsGeometry &geometry ) const
{
auto rings = extractRings( geometry.constGet() );
QgsWkbTypes::Type resultType = outWkbType( geometry.wkbType() );
std::unique_ptr<QgsMultiCurve> lineGeometry;
if ( QgsWkbTypes::flatType( resultType ) == QgsWkbTypes::MultiLineString )
lineGeometry = qgis::make_unique<QgsMultiLineString>();
else
lineGeometry = qgis::make_unique<QgsMultiCurve>();
for ( auto ring : qgis::as_const( rings ) )
lineGeometry->addGeometry( ring );
return QgsGeometry( lineGeometry.release() );
}
QgsWkbTypes::Type QgsPolygonsToLinesAlgorithm::outWkbType( QgsWkbTypes::Type polygonWkbType ) const
{
QgsWkbTypes::Type wkbType = QgsWkbTypes::NoGeometry;
if ( QgsWkbTypes::singleType( QgsWkbTypes::flatType( polygonWkbType ) ) == QgsWkbTypes::Polygon )
wkbType = QgsWkbTypes::MultiLineString;
else if ( QgsWkbTypes::singleType( QgsWkbTypes::flatType( polygonWkbType ) ) == QgsWkbTypes::CurvePolygon )
wkbType = QgsWkbTypes::MultiCurve;
if ( QgsWkbTypes::hasM( polygonWkbType ) )
wkbType = QgsWkbTypes::addM( wkbType );
if ( QgsWkbTypes::hasZ( polygonWkbType ) )
wkbType = QgsWkbTypes::addZ( wkbType );
return wkbType;
}
QList<QgsCurve *> QgsPolygonsToLinesAlgorithm::extractRings( const QgsAbstractGeometry *geom ) const
{
QList<QgsCurve *> rings;
if ( QgsGeometryCollection *collection = qgsgeometry_cast<QgsGeometryCollection *>( geom ) )
{
for ( int i = 0; i < collection->numGeometries(); ++i )
{
rings.append( extractRings( collection->geometryN( i ) ) );
}
}
else if ( QgsCurvePolygon *polygon = qgsgeometry_cast<QgsCurvePolygon *>( geom ) )
{
rings.append( polygon->exteriorRing()->clone() );
for ( int i = 0; i < polygon->numInteriorRings(); ++i )
{
rings.append( polygon->interiorRing( i )->clone() );
}
}
return rings;
}
///@endcond

View File

@ -0,0 +1,63 @@
/***************************************************************************
qgsalgorithmpolygontolines.h
---------------------
begin : January 2019
copyright : (C) 2019 by Matthias Kuhn
email : matthias@opengis.ch
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSALGORITHMPOLYGONSTOLINES_H
#define QGSALGORITHMPOLYGONSTOLINES_H
#define SIP_NO_FILE
#include "qgis.h"
#include "qgsprocessingalgorithm.h"
///@cond PRIVATE
/**
* Native convert polygons to lines algorithm
*/
class QgsPolygonsToLinesAlgorithm : public QgsProcessingFeatureBasedAlgorithm
{
public:
QgsPolygonsToLinesAlgorithm() = default;
QString name() const override;
QString displayName() const override;
QStringList tags() const override;
QString group() const override;
QString groupId() const override;
QString shortHelpString() const override;
QString shortDescription() const override;
QgsPolygonsToLinesAlgorithm *createInstance() const override SIP_FACTORY;
QList<int> inputLayerTypes() const override;
protected:
QString outputName() const override;
QgsFeatureList processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
private:
QgsGeometry convertToLines( const QgsGeometry &geometry ) const;
QList<QgsCurve *> extractRings( const QgsAbstractGeometry *geom ) const;
QgsWkbTypes::Type outWkbType( QgsWkbTypes::Type polygonWkbType ) const;
friend class TestQgsProcessingAlgs;
};
///@endcond PRIVATE
#endif // QGSALGORITHMPOLYGONSTOLINES_H

View File

@ -105,7 +105,7 @@
#include "qgsalgorithmvectorize.h"
#include "qgsalgorithmwedgebuffers.h"
#include "qgsalgorithmzonalhistogram.h"
#include "qgsalgorithmpolygonstolines.h"
///@cond PRIVATE
@ -243,6 +243,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
addAlgorithm( new QgsVariableWidthBufferByMAlgorithm() );
addAlgorithm( new QgsWedgeBuffersAlgorithm() );
addAlgorithm( new QgsZonalHistogramAlgorithm() );
addAlgorithm( new QgsPolygonsToLinesAlgorithm() );
}