Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsalgorithmfixgeometries.cpp 3 : : ----------------------------- 4 : : begin : April 2017 5 : : copyright : (C) 2017 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 "qgsalgorithmfixgeometries.h" 19 : : #include "qgsvectorlayer.h" 20 : : 21 : : ///@cond PRIVATE 22 : : 23 : 0 : QString QgsFixGeometriesAlgorithm::name() const 24 : : { 25 : 0 : return QStringLiteral( "fixgeometries" ); 26 : : } 27 : : 28 : 0 : QString QgsFixGeometriesAlgorithm::displayName() const 29 : : { 30 : 0 : return QObject::tr( "Fix geometries" ); 31 : : } 32 : : 33 : 0 : QStringList QgsFixGeometriesAlgorithm::tags() const 34 : : { 35 : 0 : return QObject::tr( "repair,invalid,geometry,make,valid" ).split( ',' ); 36 : 0 : } 37 : : 38 : 0 : QString QgsFixGeometriesAlgorithm::group() const 39 : : { 40 : 0 : return QObject::tr( "Vector geometry" ); 41 : : } 42 : : 43 : 0 : QString QgsFixGeometriesAlgorithm::groupId() const 44 : : { 45 : 0 : return QStringLiteral( "vectorgeometry" ); 46 : : } 47 : : 48 : 0 : QgsProcessingFeatureSource::Flag QgsFixGeometriesAlgorithm::sourceFlags() const 49 : : { 50 : 0 : return QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks; 51 : : } 52 : : 53 : 0 : QString QgsFixGeometriesAlgorithm::outputName() const 54 : : { 55 : 0 : return QObject::tr( "Fixed geometries" ); 56 : : } 57 : : 58 : 0 : QgsWkbTypes::Type QgsFixGeometriesAlgorithm::outputWkbType( QgsWkbTypes::Type type ) const 59 : : { 60 : 0 : return QgsWkbTypes::multiType( type ); 61 : : } 62 : : 63 : 0 : QString QgsFixGeometriesAlgorithm::shortHelpString() const 64 : : { 65 : 0 : return QObject::tr( "This algorithm attempts to create a valid representation of a given invalid geometry without " 66 : : "losing any of the input vertices. Already-valid geometries are returned without further intervention. " 67 : : "Always outputs multi-geometry layer.\n\n" 68 : : "NOTE: M values will be dropped from the output." ); 69 : : } 70 : : 71 : 0 : QgsFixGeometriesAlgorithm *QgsFixGeometriesAlgorithm::createInstance() const 72 : : { 73 : 0 : return new QgsFixGeometriesAlgorithm(); 74 : : } 75 : : 76 : 0 : bool QgsFixGeometriesAlgorithm::supportInPlaceEdit( const QgsMapLayer *l ) const 77 : : { 78 : 0 : const QgsVectorLayer *layer = qobject_cast< const QgsVectorLayer * >( l ); 79 : 0 : if ( !layer ) 80 : 0 : return false; 81 : : 82 : 0 : if ( !layer->isSpatial() || ! QgsProcessingFeatureBasedAlgorithm::supportInPlaceEdit( layer ) ) 83 : 0 : return false; 84 : : // The algorithm would drop M, so disable it if the layer has M 85 : 0 : return ! QgsWkbTypes::hasM( layer->wkbType() ); 86 : 0 : } 87 : : 88 : 0 : QgsFeatureList QgsFixGeometriesAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &, QgsProcessingFeedback *feedback ) 89 : : { 90 : 0 : if ( !feature.hasGeometry() ) 91 : 0 : return QgsFeatureList() << feature; 92 : : 93 : 0 : QgsFeature outputFeature = feature; 94 : : 95 : 0 : QgsGeometry outputGeometry = outputFeature.geometry().makeValid(); 96 : 0 : if ( outputGeometry.isNull() ) 97 : : { 98 : 0 : feedback->pushInfo( QObject::tr( "makeValid failed for feature %1 " ).arg( feature.id() ) ); 99 : 0 : outputFeature.clearGeometry(); 100 : 0 : return QgsFeatureList() << outputFeature; 101 : : } 102 : : 103 : 0 : if ( outputGeometry.wkbType() == QgsWkbTypes::Unknown || 104 : 0 : QgsWkbTypes::flatType( outputGeometry.wkbType() ) == QgsWkbTypes::GeometryCollection ) 105 : : { 106 : : // keep only the parts of the geometry collection with correct type 107 : 0 : const QVector< QgsGeometry > tmpGeometries = outputGeometry.asGeometryCollection(); 108 : 0 : QVector< QgsGeometry > matchingParts; 109 : 0 : for ( const QgsGeometry &g : tmpGeometries ) 110 : : { 111 : 0 : if ( g.type() == feature.geometry().type() ) 112 : 0 : matchingParts << g; 113 : : } 114 : 0 : if ( !matchingParts.empty() ) 115 : 0 : outputGeometry = QgsGeometry::collectGeometry( matchingParts ); 116 : : else 117 : 0 : outputGeometry = QgsGeometry(); 118 : 0 : } 119 : : 120 : 0 : outputGeometry.convertToMultiType(); 121 : 0 : if ( QgsWkbTypes::geometryType( outputGeometry.wkbType() ) != QgsWkbTypes::geometryType( feature.geometry().wkbType() ) ) 122 : : { 123 : : // don't keep geometries which have different types - e.g. lines converted to points 124 : 0 : feedback->pushInfo( QObject::tr( "Fixing geometry for feature %1 resulted in %2, geometry has been dropped." ).arg( feature.id() ).arg( QgsWkbTypes::displayString( outputGeometry.wkbType() ) ) ); 125 : 0 : outputFeature.clearGeometry(); 126 : 0 : } 127 : : else 128 : : { 129 : 0 : outputFeature.setGeometry( outputGeometry ); 130 : : } 131 : 0 : return QgsFeatureList() << outputFeature; 132 : 0 : } 133 : : 134 : : ///@endcond