Port fix geometries alg to c++

This commit is contained in:
Nyall Dawson 2017-09-14 08:01:55 +10:00
parent 07fd9cb83c
commit 7c5521ecdf
7 changed files with 77 additions and 110 deletions

View File

@ -222,11 +222,6 @@ qgis:fixeddistancebuffer: >
The miter limit parameter is only applicable for miter join styles, and controls the maximum distance from the offset curve to use when creating a mitered join.
qgis:fixgeometries: >
This algorithm attempts to create a valid representation of a given invalid geometry without losing any of the input vertices. Already-valid geometries are returned without further intervention. Always outputs multi-geometry layer.
NOTE: M values will be dropped from the output.
qgis:frequencyanalysis: >
This algorithm generates a table with frequency analysis of the values of a selected attribute from an input vector layer

View File

@ -1,101 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
FixGeometry.py
-----------------------
Date : January 2017
Copyright : (C) 2017 by Alexander Bruy
Email : alexander dot bruy 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__ = 'Alexander Bruy'
__date__ = 'January 2017'
__copyright__ = '(C) 2017, Alexander Bruy'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
from qgis.core import (QgsWkbTypes,
QgsFeatureSink,
QgsFeatureRequest,
QgsProcessingFeatureSource,
QgsGeometry,
QgsProcessing,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterFeatureSink)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
class FixGeometry(QgisAlgorithm):
INPUT = 'INPUT'
OUTPUT = 'OUTPUT'
def tags(self):
return self.tr('repair,invalid,geometry').split(',')
def group(self):
return self.tr('Vector geometry')
def __init__(self):
super().__init__()
def initAlgorithm(self, config=None):
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT, self.tr('Input layer'), [QgsProcessing.TypeVectorLine, QgsProcessing.TypeVectorPolygon]))
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Fixed geometries')))
def name(self):
return 'fixgeometries'
def displayName(self):
return self.tr('Fix geometries')
def processAlgorithm(self, parameters, context, feedback):
source = self.parameterAsSource(parameters, self.INPUT, context)
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
source.fields(), QgsWkbTypes.multiType(source.wkbType()), source.sourceCrs())
features = source.getFeatures(QgsFeatureRequest(), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
total = 100.0 / source.featureCount() if source.featureCount() else 0
for current, inputFeature in enumerate(features):
if feedback.isCanceled():
break
outputFeature = inputFeature
if inputFeature.geometry():
outputGeometry = inputFeature.geometry().makeValid()
if not outputGeometry:
feedback.pushInfo('makeValid failed for feature {}'.format(inputFeature.id()))
if outputGeometry.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(outputGeometry.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
tmpGeometries = outputGeometry.asGeometryCollection()
for g in tmpGeometries:
if g.type() == inputFeature.geometry().type():
try:
g.convertToMultiType()
outputFeature.setGeometry(QgsGeometry(g))
sink.addFeature(outputFeature, QgsFeatureSink.FastInsert)
except:
pass
feedback.setProgress(int(current * total))
continue
outputGeometry.convertToMultiType()
outputFeature.setGeometry(outputGeometry)
sink.addFeature(outputFeature, QgsFeatureSink.FastInsert)
feedback.setProgress(int(current * total))
return {self.OUTPUT: dest_id}

View File

@ -75,7 +75,6 @@ from .FieldsCalculator import FieldsCalculator
from .FieldsMapper import FieldsMapper
from .FindProjection import FindProjection
from .FixedDistanceBuffer import FixedDistanceBuffer
from .FixGeometry import FixGeometry
from .GeometryConvert import GeometryConvert
from .GeometryByExpression import GeometryByExpression
from .Gridify import Gridify
@ -216,7 +215,6 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
FieldsPyculator(),
FindProjection(),
FixedDistanceBuffer(),
FixGeometry(),
GeometryByExpression(),
GeometryConvert(),
Gridify(),

View File

@ -2729,7 +2729,7 @@ tests:
# name: expected/zonal_statistics.gml
# type: vector
- algorithm: qgis:fixgeometries
- algorithm: native:fixgeometries
name: Fix geometries
params:
INPUT:

View File

@ -928,7 +928,7 @@ QgsAbstractGeometry *_qgis_lwgeom_make_valid( const QgsAbstractGeometry *lwgeom_
}
else
{
QgsDebugMsg( "original geom converted to GEOS" );
QgsDebugMsgLevel( "original geom converted to GEOS", 4 );
}
GEOSGeometry *geosout = LWGEOM_GEOS_makeValid( geosgeom, errorMessage );

View File

@ -78,6 +78,7 @@ void QgsNativeAlgorithms::loadAlgorithms()
addAlgorithm( new QgsPromoteToMultipartAlgorithm() );
addAlgorithm( new QgsSelectByLocationAlgorithm() );
addAlgorithm( new QgsExtractByLocationAlgorithm() );
addAlgorithm( new QgsFixGeometriesAlgorithm() );
}
void QgsCentroidAlgorithm::initAlgorithm( const QVariantMap & )
@ -1614,5 +1615,56 @@ QVariantMap QgsExtractByLocationAlgorithm::processAlgorithm( const QVariantMap &
}
QString QgsFixGeometriesAlgorithm::shortHelpString() const
{
return QObject::tr( "This algorithm attempts to create a valid representation of a given invalid geometry without "
"losing any of the input vertices. Already-valid geometries are returned without further intervention. "
"Always outputs multi-geometry layer.\n\n"
"NOTE: M values will be dropped from the output." );
}
QgsFixGeometriesAlgorithm *QgsFixGeometriesAlgorithm::createInstance() const
{
return new QgsFixGeometriesAlgorithm();
}
QgsFeature QgsFixGeometriesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingFeedback *feedback )
{
if ( !feature.hasGeometry() )
return feature;
QgsFeature outputFeature = feature;
QgsGeometry outputGeometry = outputFeature.geometry().makeValid();
if ( !outputGeometry )
{
feedback->pushInfo( QObject::tr( "makeValid failed for feature %1 " ).arg( feature.id() ) );
outputFeature.clearGeometry();
return outputFeature;
}
if ( outputGeometry.wkbType() == QgsWkbTypes::Unknown ||
QgsWkbTypes::flatType( outputGeometry.geometry()->wkbType() ) == QgsWkbTypes::GeometryCollection )
{
// keep only the parts of the geometry collection with correct type
const QList< QgsGeometry > tmpGeometries = outputGeometry.asGeometryCollection();
QList< QgsGeometry > matchingParts;
for ( const QgsGeometry &g : tmpGeometries )
{
if ( g.type() == feature.geometry().type() )
matchingParts << g;
}
if ( !matchingParts.empty() )
outputGeometry = QgsGeometry::collectGeometry( matchingParts );
else
outputGeometry = QgsGeometry();
}
outputGeometry.convertToMultiType();
outputFeature.setGeometry( outputGeometry );
return outputFeature;
}
///@endcond

View File

@ -556,6 +556,29 @@ class QgsExtractByLocationAlgorithm : public QgsLocationBasedAlgorithm
};
/**
* Native repair geometries algorithm.
*/
class QgsFixGeometriesAlgorithm : public QgsProcessingFeatureBasedAlgorithm
{
public:
QgsFixGeometriesAlgorithm() = default;
QString name() const override { return QStringLiteral( "fixgeometries" ); }
QString displayName() const override { return QObject::tr( "Fix geometries" ); }
virtual QStringList tags() const override { return QObject::tr( "repair,invalid,geometry,make,valid" ).split( ',' ); }
QString group() const override { return QObject::tr( "Vector geometry" ); }
QString shortHelpString() const override;
QgsFixGeometriesAlgorithm *createInstance() const override SIP_FACTORY;
protected:
QString outputName() const override { return QObject::tr( "Fixed geometries" ); }
QgsWkbTypes::Type outputWkbType( QgsWkbTypes::Type type ) const override { return QgsWkbTypes::multiType( type ); }
QgsFeature processFeature( const QgsFeature &feature, QgsProcessingFeedback *feedback ) override;
};
///@endcond PRIVATE
#endif // QGSNATIVEALGORITHMS_H