QGIS API Documentation  3.27.0-Master (11ef3e5184)
qgsclassificationlogarithmic.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsclassificationlogarithmic.h
3  ---------------------
4  begin : September 2019
5  copyright : (C) 2019 by Denis Rouzaud
6  email : [email protected]
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include <QObject>
17 
19 #include "qgssymbollayerutils.h"
20 #include "qgsapplication.h"
21 #include "qgsprocessingcontext.h"
22 
23 
25  : QgsClassificationMethod( NoFlag, 0 )
26 {
27  QgsProcessingParameterEnum *param = new QgsProcessingParameterEnum( QStringLiteral( "ZERO_NEG_VALUES_HANDLE" ), QObject::tr( "Handling of 0 or negative values" ), QStringList() << QObject::tr( "no handling (faster)" ) << QObject::tr( "discard (slower)" ) << QObject::tr( "prepend range (slower)" ), false, 0 );
28  addParameter( param );
29 }
30 
31 
33 {
35  copyBase( c );
36  return c;
37 }
38 
40 {
41  return QObject::tr( "Logarithmic Scale" );
42 }
43 
45 {
46  return QStringLiteral( "Logarithmic" );
47 }
48 
50 {
51  return QgsApplication::getThemeIcon( "classification_methods/mClassificationLogarithmic.svg" );
52 }
53 
54 QList<double> QgsClassificationLogarithmic::calculateBreaks( double &minimum, double &maximum, const QList<double> &values, int nclasses )
55 {
56  const QgsProcessingContext context;
57  const QgsProcessingParameterDefinition *def = parameterDefinition( QStringLiteral( "ZERO_NEG_VALUES_HANDLE" ) );
59 
60  double positiveMinimum = std::numeric_limits<double>::max();
61  if ( nvh != NegativeValueHandling::NoHandling && minimum <= 0 )
62  {
63  Q_ASSERT( values.count() );
64  if ( maximum > 0 )
65  {
66  for ( int i = 0; i < values.count(); i++ )
67  {
68  if ( values.at( i ) > 0 )
69  positiveMinimum = std::min( positiveMinimum, values.at( i ) );
70  }
71  }
72  if ( positiveMinimum == std::numeric_limits<double>::max() )
73  {
74  // there is no usable values
75  if ( nvh == NegativeValueHandling::PrependBreak )
76  return QList<double>( {0} );
77  else
78  return QList<double>();
79  }
80  }
81 
82  QList<double> breaks;
83 
84  if ( positiveMinimum != std::numeric_limits<double>::max() )
85  {
86  if ( nvh == NegativeValueHandling::PrependBreak )
87  breaks << std::floor( std::log10( positiveMinimum ) );
88  else if ( nvh == NegativeValueHandling::Discard )
89  minimum = positiveMinimum; // the minimum gets updated
90  }
91  else
92  {
93  positiveMinimum = minimum;
94  }
95 
96  // get the min/max in log10 scale
97  const double actualLogMin { std::log10( positiveMinimum ) };
98  double logMin = std::floor( actualLogMin );
99  const double logMax = std::ceil( std::log10( maximum ) );
100 
101  // calculate pretty breaks
102  QList<double> prettyBreaks { QgsSymbolLayerUtils::prettyBreaks( logMin, logMax, nclasses ) };
103 
104  // If case the first class greater than the actual log min increase the minimum log
105  while ( ! prettyBreaks.isEmpty() && prettyBreaks.first() < actualLogMin )
106  {
107  logMin += 1.0;
108  prettyBreaks = QgsSymbolLayerUtils::prettyBreaks( logMin, logMax, nclasses );
109  }
110 
111  breaks.append( prettyBreaks );
112 
113  // create the value
114  for ( int i = 0; i < breaks.count(); i++ )
115  {
116  breaks[i] = std::pow( 10, breaks.at( i ) );
117  }
118 
119  return breaks;
120 }
121 
122 QString QgsClassificationLogarithmic::valueToLabel( double value ) const
123 {
124  if ( value <= 0 )
125  {
126  return QLocale().toString( value );
127  }
128  else
129  {
130  if ( std::isnan( value ) )
131  {
132  return QObject::tr( "invalid (0 or negative values in the data)" );
133  }
134  else
135  {
136  return QString( QStringLiteral( "10^%L1" ) ).arg( std::log10( value ) );
137  }
138  }
139 }
140 
141 QString QgsClassificationLogarithmic::labelForRange( double lowerValue, double upperValue, QgsClassificationMethod::ClassPosition position ) const
142 {
143  QString lowerLabel;
144  const QString upperLabel = valueToLabel( upperValue );
145 
146  switch ( position )
147  {
148  case LowerBound:
149  lowerLabel = formatNumber( lowerValue ); // avoid to have float exponent for the minimum value
150  break;
151  case Inner:
152  case UpperBound:
153  lowerLabel = valueToLabel( lowerValue );
154  break;
155  }
156 
157  return labelFormat().arg( lowerLabel, upperLabel );
158 }
159 
161 {
162  const QgsProcessingContext context;
163  const QgsProcessingParameterDefinition *def = parameterDefinition( QStringLiteral( "ZERO_NEG_VALUES_HANDLE" ) );
165 
166  return nvh != NegativeValueHandling::NoHandling;
167 }
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Implementation of a logarithmic scale method.
bool valuesRequired() const override
Returns if the method requires values to calculate the classes If not, bounds are sufficient.
NegativeValueHandling
Handling of negative and 0 values in the method.
QString labelForRange(double lowerValue, double upperValue, ClassPosition position) const override
Returns the label for a range.
QString id() const override
The id of the method as saved in the project, must be unique in registry.
QString name() const override
The readable and translate name of the method.
QgsClassificationMethod * clone() const override
Returns a clone of the method.
QIcon icon() const override
The icon of the method.
QgsClassificationMethod is an abstract class for implementations of classification methods.
QVariantMap parameterValues() const
Returns the values of the processing 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.
void addParameter(QgsProcessingParameterDefinition *definition)
Add a parameter to the method.
QString labelFormat() const
Returns the format of the label for the classes.
const QgsProcessingParameterDefinition * parameterDefinition(const QString &parameterName) const
Returns the parameter from its name.
QString formatNumber(double value) const
Format the number according to label properties.
void copyBase(QgsClassificationMethod *c) const
Copy the parameters (shall be used in clone implementation)
Contains information about the context in which a processing algorithm is executed.
Base class for the definition of processing parameters.
An enum based parameter for processing algorithms, allowing for selection from predefined values.
static int parameterAsEnum(const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context)
Evaluates the parameter with matching definition to a enum value.
static QList< double > prettyBreaks(double minimum, double maximum, int classes)
Computes a sequence of about 'classes' equally spaced round values which cover the range of values fr...
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