16 #include <QRegularExpression>    34   values.reserve( classes.count() );
    35   for ( 
int i = 0 ; i < classes.count(); i++ )
    36     values << classes.at( i ).upperBound();
    41   : mFlags( properties )
    42   , mCodeComplexity( codeComplexity )
    43   , mLabelFormat( QStringLiteral( 
"%1 - %2" ) )
    49   qDeleteAll( mParameters );
    63   const QString methodId = element.attribute( QStringLiteral( 
"id" ) );
    67   QDomElement symmetricModeElem = element.firstChildElement( QStringLiteral( 
"symmetricMode" ) );
    68   if ( !symmetricModeElem.isNull() )
    70     bool symmetricEnabled = symmetricModeElem.attribute( QStringLiteral( 
"enabled" ) ).toInt() == 1;
    71     double symmetricPoint = symmetricModeElem.attribute( QStringLiteral( 
"symmetrypoint" ) ).toDouble();
    72     bool astride = symmetricModeElem.attribute( QStringLiteral( 
"astride" ) ).toInt() == 1;
    77   QDomElement labelFormatElem = element.firstChildElement( QStringLiteral( 
"labelformat" ) );
    78   if ( !labelFormatElem.isNull() )
    80     QString format = labelFormatElem.attribute( QStringLiteral( 
"format" ), 
"%1" + QStringLiteral( 
" - " ) + 
"%2" );
    81     int precision = labelFormatElem.attribute( QStringLiteral( 
"labelprecision" ), QStringLiteral( 
"4" ) ).toInt();
    82     bool trimTrailingZeroes = labelFormatElem.attribute( QStringLiteral( 
"trimtrailingzeroes" ), QStringLiteral( 
"false" ) ) == QLatin1String( 
"true" );
    89   QDomElement parametersElem = element.firstChildElement( QStringLiteral( 
"parameters" ) );
    94   QDomElement extraElem = element.firstChildElement( QStringLiteral( 
"extraInformation" ) );
    95   if ( !extraElem.isNull() )
    96     method->
readXml( extraElem, context );
   103   QDomElement methodElem = doc.createElement( QStringLiteral( 
"classificationMethod" ) );
   105   methodElem.setAttribute( QStringLiteral( 
"id" ), 
id() );
   108   QDomElement symmetricModeElem = doc.createElement( QStringLiteral( 
"symmetricMode" ) );
   110   symmetricModeElem.setAttribute( QStringLiteral( 
"symmetrypoint" ), 
symmetryPoint() );
   111   symmetricModeElem.setAttribute( QStringLiteral( 
"astride" ), mSymmetryAstride ? 1 : 0 );
   112   methodElem.appendChild( symmetricModeElem );
   115   QDomElement labelFormatElem = doc.createElement( QStringLiteral( 
"labelFormat" ) );
   116   labelFormatElem.setAttribute( QStringLiteral( 
"format" ), 
labelFormat() );
   117   labelFormatElem.setAttribute( QStringLiteral( 
"labelprecision" ), 
labelPrecision() );
   119   methodElem.appendChild( labelFormatElem );
   122   QDomElement parametersElem = doc.createElement( QStringLiteral( 
"parameters" ) );
   124   methodElem.appendChild( parametersElem );
   127   QDomElement extraElem = doc.createElement( QStringLiteral( 
"extraInformation" ) );
   129   methodElem.appendChild( extraElem );
   137   mSymmetricEnabled = enabled;
   139   mSymmetryAstride = astride;
   147   mLabelNumberScale = 1.0;
   148   mLabelNumberSuffix.clear();
   149   while ( precision < 0 )
   152     mLabelNumberScale /= 10.0;
   153     mLabelNumberSuffix.append( 
'0' );
   159   static const QRegularExpression RE_TRAILING_ZEROES = QRegularExpression( 
"[.,]?0*$" );
   160   static const QRegularExpression RE_NEGATIVE_ZERO = QRegularExpression( 
"^\\-0(?:[.,]0*)?$" );
   161   if ( mLabelPrecision > 0 )
   163     QString valueStr = QLocale().toString( value, 
'f', mLabelPrecision );
   164     if ( mLabelTrimTrailingZeroes )
   165       valueStr = valueStr.remove( RE_TRAILING_ZEROES );
   166     if ( RE_NEGATIVE_ZERO.match( valueStr ).hasMatch() )
   167       valueStr = valueStr.mid( 1 );
   172     QString valueStr = QLocale().toString( value * mLabelNumberScale, 
'f', 0 );
   173     if ( valueStr == QLatin1String( 
"-0" ) )
   175     if ( valueStr != QLatin1String( 
"0" ) )
   176       valueStr = valueStr + mLabelNumberSuffix;
   183   mParameters.append( definition );
   190     if ( def->name() == parameterName )
   199   mParameterValues = values;
   200   for ( 
auto it = mParameterValues.constBegin(); it != mParameterValues.constEnd(); ++it )
   211   if ( expression.isEmpty() )
   212     return QList<QgsClassificationRange>();
   217   QList<double> values;
   228     if ( !ok || values.isEmpty() )
   229       return QList<QgsClassificationRange>();
   231     auto result = std::minmax_element( values.begin(), values.end() );
   232     minimum = *result.first;
   233     maximum = *result.second;
   242   QList<double> breaks = calculateBreaks( minimum, maximum, values, nclasses );
   243   breaks.insert( 0, minimum );
   245   return breaksToClasses( breaks );
   250   auto result = std::minmax_element( values.begin(), values.end() );
   251   double minimum = *result.first;
   252   double maximum = *result.second;
   255   QList<double> breaks = calculateBreaks( minimum, maximum, values, nclasses );
   256   breaks.insert( 0, minimum );
   258   return breaksToClasses( breaks );
   265     QgsDebugMsg( QStringLiteral( 
"The classification method %1 tries to calculate classes without values while they are required." ).arg( 
name() ) );
   269   QList<double> breaks = calculateBreaks( minimum, maximum, QList<double>(), nclasses );
   270   breaks.insert( 0, minimum );
   272   return breaksToClasses( breaks );
   275 QList<QgsClassificationRange> QgsClassificationMethod::breaksToClasses( 
const QList<double> &breaks )
 const   277   QList<QgsClassificationRange> 
classes;
   279   for ( 
int i = 1; i < breaks.count(); i++ )
   282     const double lowerValue = breaks.at( i - 1 );
   283     const double upperValue = breaks.at( i );
   288     else if ( i == breaks.count() - 1 )
   291     QString label = 
labelForRange( lowerValue, upperValue, pos );
   305   if ( breaks.count() < 2 )
   308   std::sort( breaks.begin(), breaks.end() );
   310   double distBelowSymmetricValue = std::fabs( breaks[0] - symmetryPoint );
   311   double distAboveSymmetricValue = std::fabs( breaks[ breaks.size() - 2 ] - 
symmetryPoint ) ;
   312   double absMin = std::min( distAboveSymmetricValue, distBelowSymmetricValue );
   315   for ( 
int i = 0; i <= breaks.size() - 2; ++i )
   318     if ( std::fabs( breaks.at( i ) - 
symmetryPoint ) >= ( absMin - std::fabs( breaks[0] - breaks[1] ) / 100. ) )
   320       breaks.removeAt( i );
   327     breaks.removeAt( breaks.indexOf( symmetryPoint ) );
   340   const QString lowerLabel = valueToLabel( lowerValue );
   341   const QString upperLabel = valueToLabel( upperValue );
   343   return labelFormat().arg( lowerLabel ).arg( upperLabel );
 QgsClassificationMethod * method(const QString &id)
Returns a new instance of the method for the given id. 
 
The class is used as a container of context for various read/write operations on other objects...
 
virtual QString labelForRange(double lowerValue, double upperValue, ClassPosition position=Inner) const
Returns the label for a range. 
 
QList< QgsClassificationRange > classes(const QgsVectorLayer *layer, const QString &expression, int nclasses)
This will calculate the classes for a given layer to define the classes. 
 
QString formatNumber(double value) const
Format the number according to label properties. 
 
const QgsProcessingParameterDefinition * parameterDefinition(const QString ¶meterName) const
Returns the parameter from its name. 
 
static QList< double > getDoubleValues(const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly=false, int *nullCount=nullptr, QgsFeedback *feedback=nullptr)
Fetches all double values from a specified field name or expression. 
 
int codeComplexity() const
Code complexity as the exponent in Big O notation. 
 
QgsClassificationRange contains the information about a classification range. 
 
virtual bool valuesRequired() const
Returns if the method requires values to calculate the classes If not, bounds are sufficient...
 
virtual void writeXml(QDomElement &element, const QgsReadWriteContext &context) const
Writes extra information about the method. 
 
The class is not at a bound. 
 
static const int MAX_PRECISION
 
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) const
Saves the method to a DOM element and return it. 
 
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
 
double lowerValue() const
 
The class is at the upper bound. 
 
void addParameter(QgsProcessingParameterDefinition *definition)
Add a parameter to the method. 
 
void setSymmetricMode(bool enabled, double symmetryPoint=0, bool symmetryAstride=false)
Defines if the symmetric mode is enables and configures its parameters. 
 
The class is at the lower bound. 
 
int indexFromName(const QString &fieldName) const
Gets the field index from the field name. 
 
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement. 
 
QgsFields fields() const FINAL
Returns the list of fields of this layer. 
 
double symmetryPoint() const
Returns the symmetry point for symmetric mode. 
 
int labelPrecision() const
Returns the precision for the formatting of the labels. 
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary). 
 
void setLabelFormat(const QString &format)
Defines the format of the labels for the classes, using %1 and %2 for the bounds. ...
 
bool labelTrimTrailingZeroes() const
Returns if the trailing 0 are trimmed in the label. 
 
QVariant minimumValue(int index) const FINAL
Returns the minimum value for an attribute column or an invalid variant in case of error...
 
void setLabelPrecision(int labelPrecision)
Defines the precision for the formatting of the labels. 
 
void copyBase(QgsClassificationMethod *c) const
Copy the parameters (shall be used in clone implementation) 
 
static const int MIN_PRECISION
 
bool symmetricModeEnabled() const
Returns if the symmetric mode is enabled. 
 
virtual void readXml(const QDomElement &element, const QgsReadWriteContext &context)
Reads extra information to apply it to the method. 
 
QString labelFormat() const
Returns the format of the label for the classes. 
 
QgsClassificationMethod(MethodProperties properties=NoFlag, int codeComplexity=1)
Creates a classification method. 
 
static QgsClassificationMethodRegistry * classificationMethodRegistry()
Returns the application's classification methods registry, used in graduated renderer. 
 
static QList< double > rangesToBreaks(const QList< QgsClassificationRange > &classes)
Transforms a list of classes to a list of breaks. 
 
Base class for the definition of processing parameters. 
 
QVariantMap parameterValues() const
Returns the values of the processing parameters. 
 
double upperValue() const
 
ClassPosition
Defines the class position. 
 
static void makeBreaksSymmetric(QList< double > &breaks, double symmetryPoint, bool astride)
Remove the breaks that are above the existing opposite sign classes to keep colors symmetrically bala...
 
void setLabelTrimTrailingZeroes(bool trimTrailingZeroes)
Defines if the trailing 0 are trimmed in the label. 
 
void setParameterValues(const QVariantMap &values)
Defines the values of the additional parameters. 
 
QVariant maximumValue(int index) const FINAL
Returns the maximum value for an attribute column or an invalid variant in case of error...
 
Represents a vector layer which manages a vector based data sets. 
 
QgsClassificationMethod is an abstract class for implementations of classification methods...
 
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement. 
 
virtual QString name() const =0
The readable and translate name of the method. 
 
virtual ~QgsClassificationMethod()
 
static QgsClassificationMethod * create(const QDomElement &element, const QgsReadWriteContext &context)
Reads the DOM element and return a new classification method from it.