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