Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgsalgorithmsmooth.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 "qgsalgorithmsmooth.h" 19 : : 20 : : ///@cond PRIVATE 21 : : 22 : 0 : QString QgsSmoothAlgorithm::name() const 23 : : { 24 : 0 : return QStringLiteral( "smoothgeometry" ); 25 : : } 26 : : 27 : 0 : QString QgsSmoothAlgorithm::displayName() const 28 : : { 29 : 0 : return QObject::tr( "Smooth" ); 30 : : } 31 : : 32 : 0 : QStringList QgsSmoothAlgorithm::tags() const 33 : : { 34 : 0 : return QObject::tr( "smooth,curve,generalize,round,bend,corners" ).split( ',' ); 35 : 0 : } 36 : : 37 : 0 : QString QgsSmoothAlgorithm::group() const 38 : : { 39 : 0 : return QObject::tr( "Vector geometry" ); 40 : : } 41 : : 42 : 0 : QString QgsSmoothAlgorithm::groupId() const 43 : : { 44 : 0 : return QStringLiteral( "vectorgeometry" ); 45 : : } 46 : : 47 : 0 : QString QgsSmoothAlgorithm::outputName() const 48 : : { 49 : 0 : return QObject::tr( "Smoothed" ); 50 : : } 51 : : 52 : 0 : QgsProcessing::SourceType QgsSmoothAlgorithm::outputLayerType() const 53 : : { 54 : 0 : return QgsProcessing::TypeVectorLine; 55 : : } 56 : : 57 : 0 : QString QgsSmoothAlgorithm::shortHelpString() const 58 : : { 59 : 0 : return QObject::tr( "This algorithm smooths the geometries in a line or polygon layer. It creates a new layer with the " 60 : : "same features as the ones in the input layer, but with geometries containing a higher number of vertices " 61 : : "and corners in the geometries smoothed out.\n\n" 62 : : "The iterations parameter dictates how many smoothing iterations will be applied to each " 63 : : "geometry. A higher number of iterations results in smoother geometries with the cost of " 64 : : "greater number of nodes in the geometries.\n\n" 65 : : "The offset parameter controls how \"tightly\" the smoothed geometries follow the original geometries. " 66 : : "Smaller values results in a tighter fit, and larger values will create a looser fit.\n\n" 67 : : "The maximum angle parameter can be used to prevent smoothing of " 68 : : "nodes with large angles. Any node where the angle of the segments to either " 69 : : "side is larger than this will not be smoothed. For example, setting the maximum " 70 : : "angle to 90 degrees or lower would preserve right angles in the geometry.\n\n" 71 : : "If input geometries contain Z or M values, these will also be smoothed and the output " 72 : : "geometry will retain the same dimensionality as the input geometry." ); 73 : : } 74 : : 75 : 0 : QgsSmoothAlgorithm *QgsSmoothAlgorithm::createInstance() const 76 : : { 77 : 0 : return new QgsSmoothAlgorithm(); 78 : 0 : } 79 : : 80 : 0 : QList<int> QgsSmoothAlgorithm::inputLayerTypes() const 81 : : { 82 : 0 : return QList<int>() << QgsProcessing::TypeVectorLine << QgsProcessing::TypeVectorPolygon; 83 : 0 : } 84 : : 85 : 0 : void QgsSmoothAlgorithm::initParameters( const QVariantMap & ) 86 : : { 87 : 0 : std::unique_ptr< QgsProcessingParameterNumber > iterations = std::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "ITERATIONS" ), 88 : 0 : QObject::tr( "Iterations" ), QgsProcessingParameterNumber::Integer, 89 : 0 : 1, false, 1, 10 ); 90 : 0 : iterations->setIsDynamic( true ); 91 : 0 : iterations->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "ITERATIONS" ), QObject::tr( "Iterations" ), QgsPropertyDefinition::IntegerPositiveGreaterZero ) ); 92 : 0 : iterations->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) ); 93 : 0 : addParameter( iterations.release() ); 94 : : 95 : 0 : std::unique_ptr< QgsProcessingParameterNumber > offset = std::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "OFFSET" ), 96 : 0 : QObject::tr( "Offset" ), QgsProcessingParameterNumber::Double, 97 : 0 : 0.25, false, 0.0, 0.5 ); 98 : 0 : offset->setIsDynamic( true ); 99 : 0 : offset->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "OFFSET" ), QObject::tr( "Offset" ), QgsPropertyDefinition::Double0To1 ) ); 100 : 0 : offset->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) ); 101 : 0 : addParameter( offset.release() ); 102 : : 103 : 0 : std::unique_ptr< QgsProcessingParameterNumber > maxAngle = std::make_unique< QgsProcessingParameterNumber >( QStringLiteral( "MAX_ANGLE" ), 104 : 0 : QObject::tr( "Maximum node angle to smooth" ), QgsProcessingParameterNumber::Double, 105 : 0 : 180.0, false, 0.0, 180.0 ); 106 : 0 : maxAngle->setIsDynamic( true ); 107 : 0 : maxAngle->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "MAX_ANGLE" ), QObject::tr( "Maximum node angle to smooth" ), QgsPropertyDefinition::Rotation ) ); 108 : 0 : maxAngle->setDynamicLayerParameterName( QStringLiteral( "INPUT" ) ); 109 : 0 : addParameter( maxAngle.release() ); 110 : 0 : } 111 : : 112 : 0 : bool QgsSmoothAlgorithm::prepareAlgorithm( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback * ) 113 : : { 114 : 0 : mIterations = parameterAsInt( parameters, QStringLiteral( "ITERATIONS" ), context ); 115 : 0 : mDynamicIterations = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "ITERATIONS" ) ); 116 : 0 : if ( mDynamicIterations ) 117 : 0 : mIterationsProperty = parameters.value( QStringLiteral( "ITERATIONS" ) ).value< QgsProperty >(); 118 : : 119 : 0 : mOffset = parameterAsDouble( parameters, QStringLiteral( "OFFSET" ), context ); 120 : 0 : mDynamicOffset = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "OFFSET" ) ); 121 : 0 : if ( mDynamicOffset ) 122 : 0 : mOffsetProperty = parameters.value( QStringLiteral( "OFFSET" ) ).value< QgsProperty >(); 123 : : 124 : 0 : mMaxAngle = parameterAsDouble( parameters, QStringLiteral( "MAX_ANGLE" ), context ); 125 : 0 : mDynamicMaxAngle = QgsProcessingParameters::isDynamic( parameters, QStringLiteral( "MAX_ANGLE" ) ); 126 : 0 : if ( mDynamicMaxAngle ) 127 : 0 : mMaxAngleProperty = parameters.value( QStringLiteral( "MAX_ANGLE" ) ).value< QgsProperty >(); 128 : : 129 : 0 : return true; 130 : 0 : } 131 : : 132 : 0 : QgsFeatureList QgsSmoothAlgorithm::processFeature( const QgsFeature &feature, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) 133 : : { 134 : 0 : QgsFeature f = feature; 135 : 0 : if ( f.hasGeometry() ) 136 : : { 137 : 0 : int iterations = mIterations; 138 : 0 : if ( mDynamicIterations ) 139 : 0 : iterations = mIterationsProperty.valueAsInt( context.expressionContext(), iterations ); 140 : : 141 : 0 : double offset = mOffset; 142 : 0 : if ( mDynamicOffset ) 143 : 0 : offset = mOffsetProperty.valueAsDouble( context.expressionContext(), offset ); 144 : : 145 : 0 : double maxAngle = mMaxAngle; 146 : 0 : if ( mDynamicMaxAngle ) 147 : 0 : maxAngle = mMaxAngleProperty.valueAsDouble( context.expressionContext(), maxAngle ); 148 : : 149 : 0 : QgsGeometry outputGeometry = f.geometry().smooth( iterations, offset, -1, maxAngle ); 150 : 0 : if ( outputGeometry.isNull() ) 151 : : { 152 : 0 : feedback->reportError( QObject::tr( "Error smoothing geometry %1" ).arg( feature.id() ) ); 153 : 0 : } 154 : 0 : f.setGeometry( outputGeometry ); 155 : 0 : } 156 : 0 : return QgsFeatureList() << f; 157 : 0 : } 158 : : 159 : 0 : QgsProcessingFeatureSource::Flag QgsSmoothAlgorithm::sourceFlags() const 160 : : { 161 : 0 : return QgsProcessingFeatureSource::FlagSkipGeometryValidityChecks; 162 : : } 163 : : 164 : : ///@endcond 165 : : 166 : :