QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
qgsclassificationstandarddeviation.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsclassificationstandarddeviation.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 
20 #include "qgsapplication.h"
21 
22 const QString QgsClassificationStandardDeviation::METHOD_ID = QStringLiteral( "StdDev" );
23 
24 
26  : QgsClassificationMethod( SymmetricModeAvailable )
27 {
28 
29 }
30 
32 {
33  return QObject::tr( "Standard Deviation" );
34 }
35 
37 {
38  return METHOD_ID;
39 }
40 
42 {
44  copyBase( c );
45  c->mStdDev = mStdDev;
46  return c;
47 }
48 
50 {
51  return QgsApplication::getThemeIcon( "classification_methods/mClassificationStandardDeviation.svg" );
52 }
53 
54 
55 QList<double> QgsClassificationStandardDeviation::calculateBreaks( double minimum, double maximum,
56  const QList<double> &values, int nclasses )
57 {
58  // C++ implementation of the standard deviation class interval algorithm
59  // as implemented in the 'classInt' package available for the R statistical
60  // prgramming language.
61 
62  // Returns breaks based on 'prettyBreaks' of the centred and scaled
63  // values of 'values', and may have a number of classes different from 'classes'.
64 
65  // If there are no values to process: bail out
66  if ( values.isEmpty() )
67  return QList<double>();
68 
69  double mean = 0.0;
70  mStdDev = 0.0;
71  int n = values.count();
72 
73  for ( int i = 0; i < n; i++ )
74  {
75  mean += values[i];
76  }
77  mean = mean / static_cast< double >( n );
78 
79  double sd = 0.0;
80  for ( int i = 0; i < n; i++ )
81  {
82  sd = values[i] - mean;
83  mStdDev += sd * sd;
84  }
85  mStdDev = std::sqrt( mStdDev / n );
86 
87  // if not symmetric, the symmetry point is the mean
88  mEffectiveSymmetryPoint = symmetricModeEnabled() ? symmetryPoint() : mean;
89 
90  QList<double> breaks = QgsSymbolLayerUtils::prettyBreaks( ( minimum - mEffectiveSymmetryPoint ) / mStdDev, ( maximum - mEffectiveSymmetryPoint ) / mStdDev, nclasses );
91  makeBreaksSymmetric( breaks, 0.0, symmetryAstride() ); //0.0 because breaks where computed on a centered distribution
92 
93  for ( int i = 0; i < breaks.count(); i++ )
94  breaks[i] = ( breaks[i] * mStdDev ) + mEffectiveSymmetryPoint;
95 
96  return breaks;
97 }
98 
99 QString QgsClassificationStandardDeviation::labelForRange( const double lowerValue, const double upperValue, QgsClassificationMethod::ClassPosition position ) const
100 {
101  const QString lowerLabel = valueToLabel( lowerValue );
102  const QString upperLabel = valueToLabel( upperValue );
103 
104  switch ( position )
105  {
106  case LowerBound:
107  return QStringLiteral( "< %1" ).arg( upperLabel );
108  case Inner:
109  {
110  QString label( labelFormat() );
111  label.replace( QLatin1String( "%1" ), lowerLabel ).replace( QLatin1String( "%2" ), upperLabel );
112  return label;
113  }
114  case UpperBound:
115  return QStringLiteral( "≥ %1" ).arg( lowerLabel );
116  }
117  return QString();
118 }
119 
120 
121 QString QgsClassificationStandardDeviation::valueToLabel( const double value ) const
122 {
123  double normalized = ( value - mEffectiveSymmetryPoint ) / mStdDev;
124  return QObject::tr( " %1 Std Dev" ).arg( QString::number( normalized, 'f', 2 ) );
125 }
126 
127 
128 void QgsClassificationStandardDeviation::writeXml( QDomElement &element, const QgsReadWriteContext &context ) const
129 {
130  Q_UNUSED( context )
131 
132  element.setAttribute( QStringLiteral( "std_dev" ), QString::number( mStdDev, 'f', 16 ) );
133  element.setAttribute( QStringLiteral( "effective_symmetry_point" ), QString::number( mEffectiveSymmetryPoint, 'f', 16 ) );
134 }
135 
136 void QgsClassificationStandardDeviation::readXml( const QDomElement &element, const QgsReadWriteContext &context )
137 {
138  Q_UNUSED( context )
139 
140  mStdDev = element.attribute( QStringLiteral( "std_dev" ), QStringLiteral( "1.0" ) ).toDouble();
141  mEffectiveSymmetryPoint = element.attribute( QStringLiteral( "effective_symmetry_point" ), QStringLiteral( "0.0" ) ).toDouble();
142 }
The class is used as a container of context for various read/write operations on other objects...
QString id() const override
The id of the method as saved in the project, must be unique in registry.
bool symmetryAstride() const
Returns if the symmetric mode is astride if true, it will remove the symmetry point break so that the...
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
The class is not at a bound.
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
The class is at the upper bound.
The class is at the lower bound.
double symmetryPoint() const
Returns the symmetry point for symmetric mode.
QString labelForRange(double lowerValue, double upperValue, ClassPosition position) const override
Returns the label for a range.
void copyBase(QgsClassificationMethod *c) const
Copy the parameters (shall be used in clone implementation)
bool symmetricModeEnabled() const
Returns if the symmetric mode is enabled.
QString labelFormat() const
Returns the format of the label for the classes.
void readXml(const QDomElement &element, const QgsReadWriteContext &context) override
Reads extra information to apply it to the method.
static QList< double > prettyBreaks(double minimum, double maximum, int classes)
Computes a sequence of about &#39;classes&#39; equally spaced round values which cover the range of values fr...
void writeXml(QDomElement &element, const QgsReadWriteContext &context) const override
Writes extra information about the method.
QgsClassificationCustom is an implementation of QgsClassificationMethod based on standard deviation...
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...
QIcon icon() const override
The icon of the method.
QgsClassificationMethod * clone() const override
Returns a clone of the method.
QString name() const override
The readable and translate name of the method.
QgsClassificationMethod is an abstract class for implementations of classification methods...