16#include <QRegularExpression> 
   35  values.reserve( 
classes.count() );
 
   36  for ( 
int i = 0 ; i < 
classes.count(); i++ )
 
   37    values << 
classes.at( i ).upperBound();
 
 
   42  : mFlags( properties )
 
   43  , mCodeComplexity( codeComplexity )
 
   44  , mLabelFormat( QStringLiteral( 
"%1 - %2" ) )
 
 
   50  qDeleteAll( mParameters );
 
 
   55  c->setSymmetricMode( mSymmetricEnabled, mSymmetryPoint, mSymmetryAstride );
 
   56  c->setLabelFormat( mLabelFormat );
 
   57  c->setLabelPrecision( mLabelPrecision );
 
   58  c->setLabelTrimTrailingZeroes( mLabelTrimTrailingZeroes );
 
   59  c->setParameterValues( mParameterValues );
 
 
   64  const QString methodId = element.attribute( QStringLiteral( 
"id" ) );
 
   68  QDomElement symmetricModeElem = element.firstChildElement( QStringLiteral( 
"symmetricMode" ) );
 
   69  if ( !symmetricModeElem.isNull() )
 
   71    bool symmetricEnabled = symmetricModeElem.attribute( QStringLiteral( 
"enabled" ) ).toInt() == 1;
 
   72    double symmetricPoint = symmetricModeElem.attribute( QStringLiteral( 
"symmetrypoint" ) ).toDouble();
 
   73    bool astride = symmetricModeElem.attribute( QStringLiteral( 
"astride" ) ).toInt() == 1;
 
   74    method->setSymmetricMode( symmetricEnabled, symmetricPoint, astride );
 
   78  QDomElement labelFormatElem = element.firstChildElement( QStringLiteral( 
"labelFormat" ) );
 
   79  if ( !labelFormatElem.isNull() )
 
   81    QString format = labelFormatElem.attribute( QStringLiteral( 
"format" ), 
"%1" + QStringLiteral( 
" - " ) + 
"%2" );
 
   82    int precision = labelFormatElem.attribute( QStringLiteral( 
"labelprecision" ), QStringLiteral( 
"4" ) ).toInt();
 
   83    bool trimTrailingZeroes = labelFormatElem.attribute( QStringLiteral( 
"trimtrailingzeroes" ), QStringLiteral( 
"false" ) ) == QLatin1String( 
"true" );
 
   84    method->setLabelFormat( format );
 
   86    method->setLabelTrimTrailingZeroes( trimTrailingZeroes );
 
   90  QDomElement parametersElem = element.firstChildElement( QStringLiteral( 
"parameters" ) );
 
   95  QDomElement extraElem = element.firstChildElement( QStringLiteral( 
"extraInformation" ) );
 
   96  if ( !extraElem.isNull() )
 
   97    method->readXml( extraElem, context );
 
 
  104  QDomElement methodElem = doc.createElement( QStringLiteral( 
"classificationMethod" ) );
 
  106  methodElem.setAttribute( QStringLiteral( 
"id" ), 
id() );
 
  109  QDomElement symmetricModeElem = doc.createElement( QStringLiteral( 
"symmetricMode" ) );
 
  111  symmetricModeElem.setAttribute( QStringLiteral( 
"symmetrypoint" ), 
symmetryPoint() );
 
  112  symmetricModeElem.setAttribute( QStringLiteral( 
"astride" ), mSymmetryAstride ? 1 : 0 );
 
  113  methodElem.appendChild( symmetricModeElem );
 
  116  QDomElement labelFormatElem = doc.createElement( QStringLiteral( 
"labelFormat" ) );
 
  117  labelFormatElem.setAttribute( QStringLiteral( 
"format" ), 
labelFormat() );
 
  118  labelFormatElem.setAttribute( QStringLiteral( 
"labelprecision" ), 
labelPrecision() );
 
  120  methodElem.appendChild( labelFormatElem );
 
  123  QDomElement parametersElem = doc.createElement( QStringLiteral( 
"parameters" ) );
 
  125  methodElem.appendChild( parametersElem );
 
  128  QDomElement extraElem = doc.createElement( QStringLiteral( 
"extraInformation" ) );
 
  130  methodElem.appendChild( extraElem );
 
 
  138  mSymmetricEnabled = enabled;
 
  140  mSymmetryAstride = astride;
 
 
  148  mLabelNumberScale = 1.0;
 
  149  mLabelNumberSuffix.clear();
 
  153    mLabelNumberScale /= 10.0;
 
  154    mLabelNumberSuffix.append( 
'0' );
 
 
  160  static const QRegularExpression RE_TRAILING_ZEROES = QRegularExpression( 
"[.,]?0*$" );
 
  161  static const QRegularExpression RE_NEGATIVE_ZERO = QRegularExpression( 
"^\\-0(?:[.,]0*)?$" );
 
  162  if ( mLabelPrecision > 0 )
 
  164    QString valueStr = QLocale().toString( value, 
'f', mLabelPrecision );
 
  165    if ( mLabelTrimTrailingZeroes )
 
  166      valueStr = valueStr.remove( RE_TRAILING_ZEROES );
 
  167    if ( RE_NEGATIVE_ZERO.match( valueStr ).hasMatch() )
 
  168      valueStr = valueStr.mid( 1 );
 
  173    QString valueStr = QLocale().toString( value * mLabelNumberScale, 
'f', 0 );
 
  174    if ( valueStr == QLatin1String( 
"-0" ) )
 
  176    if ( valueStr != QLatin1String( 
"0" ) )
 
  177      valueStr = valueStr + mLabelNumberSuffix;
 
 
  184  mParameters.append( definition );
 
 
  191    if ( def->name() == parameterName )
 
 
  200  mParameterValues = values;
 
  201  for ( 
auto it = mParameterValues.constBegin(); it != mParameterValues.constEnd(); ++it )
 
 
  213  return classesV2( layer, expression, nclasses, error );
 
 
  218  if ( expression.isEmpty() )
 
  219    return QList<QgsClassificationRange>();
 
  224  QList<double> values;
 
  235    if ( !ok || values.isEmpty() )
 
  236      return QList<QgsClassificationRange>();
 
  238    auto result = std::minmax_element( values.begin(), values.end() );
 
  239    minimum = *result.first;
 
  240    maximum = *result.second;
 
  247    minimum = minVal.toDouble();
 
  248    maximum = maxVal.toDouble();
 
  252  QList<double> breaks = calculateBreaks( minimum, maximum, values, nclasses, error );
 
  253  breaks.insert( 0, minimum );
 
  255  return breaksToClasses( breaks );
 
 
  260  auto result = std::minmax_element( values.begin(), values.end() );
 
  261  double minimum = *result.first;
 
  262  double maximum = *result.second;
 
  266  QList<double> breaks = calculateBreaks( minimum, maximum, values, nclasses, error );
 
  269  breaks.insert( 0, minimum );
 
  271  return breaksToClasses( breaks );
 
 
  278    QgsDebugError( QStringLiteral( 
"The classification method %1 tries to calculate classes without values while they are required." ).arg( 
name() ) );
 
  283  QList<double> breaks = calculateBreaks( minimum, maximum, QList<double>(), nclasses, error );
 
  286  breaks.insert( 0, minimum );
 
  288  return breaksToClasses( breaks );
 
 
  291QList<QgsClassificationRange> QgsClassificationMethod::breaksToClasses( 
const QList<double> &breaks )
 const 
  293  QList<QgsClassificationRange> 
classes;
 
  295  for ( 
int i = 1; i < breaks.count(); i++ )
 
  298    const double lowerValue = breaks.at( i - 1 );
 
  299    const double upperValue = breaks.at( i );
 
  304    else if ( i == breaks.count() - 1 )
 
  307    QString label = 
labelForRange( lowerValue, upperValue, pos );
 
  321  if ( breaks.count() < 2 )
 
  324  std::sort( breaks.begin(), breaks.end() );
 
  326  double distBelowSymmetricValue = std::fabs( breaks[0] - 
symmetryPoint );
 
  327  double distAboveSymmetricValue = std::fabs( breaks[ breaks.size() - 2 ] - 
symmetryPoint ) ;
 
  328  double absMin = std::min( distAboveSymmetricValue, distBelowSymmetricValue );
 
  331  for ( 
int i = 0; i <= breaks.size() - 2; ++i )
 
  334    if ( std::fabs( breaks.at( i ) - 
symmetryPoint ) >= ( absMin - std::fabs( breaks[0] - breaks[1] ) / 100. ) )
 
  336      breaks.removeAt( i );
 
 
  356  const QString lowerLabel = valueToLabel( lowerValue );
 
  357  const QString upperLabel = valueToLabel( upperValue );
 
  359  return labelFormat().replace( QLatin1String( 
"%1" ), lowerLabel ).replace( QLatin1String( 
"%2" ), upperLabel );
 
 
static QgsClassificationMethodRegistry * classificationMethodRegistry()
Returns the application's classification methods registry, used in graduated renderer.
 
std::unique_ptr< QgsClassificationMethod > method(const QString &id)
Returns a new instance of the method for the given id.
 
QgsClassificationMethod is an abstract class for implementations of classification methods.
 
double symmetryPoint() const
Returns the symmetry point for symmetric mode.
 
bool symmetricModeEnabled() const
Returns if the symmetric mode is enabled.
 
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...
 
static std::unique_ptr< QgsClassificationMethod > create(const QDomElement &element, const QgsReadWriteContext &context)
Reads the DOM element and return a new classification method from it.
 
QFlags< MethodProperty > MethodProperties
 
Q_DECL_DEPRECATED QList< QgsClassificationRange > classes(const QgsVectorLayer *layer, const QString &expression, int nclasses)
This will calculate the classes for a given layer to define the classes.
 
int labelPrecision() const
Returns the precision for the formatting of the labels.
 
QVariantMap parameterValues() const
Returns the values of the processing parameters.
 
void setSymmetricMode(bool enabled, double symmetryPoint=0, bool symmetryAstride=false)
Defines if the symmetric mode is enables and configures its parameters.
 
ClassPosition
Defines the class position.
 
@ LowerBound
The class is at the lower bound.
 
@ UpperBound
The class is at the upper bound.
 
@ Inner
The class is not at a bound.
 
static const int MIN_PRECISION
 
void addParameter(QgsProcessingParameterDefinition *definition)
Add a parameter to the method.
 
static QList< double > rangesToBreaks(const QList< QgsClassificationRange > &classes)
Transforms a list of classes to a list of breaks.
 
virtual void writeXml(QDomElement &element, const QgsReadWriteContext &context) const
Writes extra information about the method.
 
QString labelFormat() const
Returns the format of the label for the classes.
 
virtual bool valuesRequired() const
Returns if the method requires values to calculate the classes If not, bounds are sufficient.
 
void setParameterValues(const QVariantMap &values)
Defines the values of the additional parameters.
 
virtual QString name() const =0
The readable and translate name of the method.
 
QgsClassificationMethod(MethodProperties properties=NoFlag, int codeComplexity=1)
Creates a classification method.
 
const QgsProcessingParameterDefinition * parameterDefinition(const QString ¶meterName) const
Returns the parameter from its name.
 
QString formatNumber(double value) const
Format the number according to label properties.
 
static const int MAX_PRECISION
 
bool labelTrimTrailingZeroes() const
Returns if the trailing 0 are trimmed in the label.
 
void setLabelPrecision(int labelPrecision)
Defines the precision for the formatting of the labels.
 
QList< QgsClassificationRange > classesV2(const QgsVectorLayer *layer, const QString &expression, int nclasses, QString &error)
This will calculate the classes for a given layer to define the classes.
 
void copyBase(QgsClassificationMethod *c) const
Copy the parameters (shall be used in clone implementation)
 
virtual QString labelForRange(double lowerValue, double upperValue, ClassPosition position=Inner) const
Returns the label for a range.
 
virtual ~QgsClassificationMethod()
 
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) const
Saves the method to a DOM element and return it.
 
QgsClassificationRange contains the information about a classification range.
 
Q_INVOKABLE int indexFromName(const QString &fieldName) const
Gets the field index from the field name.
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
 
Base class for the definition of processing parameters.
 
The class is used as a container of context for various read/write operations on other objects.
 
double upperValue() const
Returns the upper bound of the range.
 
double lowerValue() const
Returns the lower bound of the range.
 
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.
 
Represents a vector layer which manages a vector based data sets.
 
void minimumAndMaximumValue(int index, QVariant &minimum, QVariant &maximum) const
Calculates both the minimum and maximum value for an attribute column.
 
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
 
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
 
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
 
#define QgsDebugError(str)