1 /***************************************************************************
2     qgsclassificationquantile.h
3     ---------------------
4     begin                : September 2019
5     copyright            : (C) 2019 by Denis Rouzaud
6     email                : denis@opengis.ch
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 
17 #include "qgsclassificationquantile.h"
18 #include "qgsapplication.h"
19 
QgsClassificationQuantile()20 QgsClassificationQuantile::QgsClassificationQuantile()
21   : QgsClassificationMethod()
22 {
23 }
24 
name() const25 QString QgsClassificationQuantile::name() const
26 {
27   return QObject::tr( "Equal Count (Quantile)" );
28 }
29 
id() const30 QString QgsClassificationQuantile::id() const
31 {
32   return QStringLiteral( "Quantile" );
33 }
34 
clone() const35 QgsClassificationMethod *QgsClassificationQuantile::clone() const
36 {
37   QgsClassificationQuantile *c = new QgsClassificationQuantile();
38   copyBase( c );
39   return c;
40 }
41 
icon() const42 QIcon QgsClassificationQuantile::icon() const
43 {
44   return QgsApplication::getThemeIcon( "classification_methods/mClassificationEqualCount.svg" );
45 }
46 
47 
calculateBreaks(double & minimum,double & maximum,const QList<double> & values,int nclasses)48 QList<double> QgsClassificationQuantile::calculateBreaks( double &minimum, double &maximum,
49     const QList<double> &values, int nclasses )
50 {
51   Q_UNUSED( minimum )
52   Q_UNUSED( maximum )
53 
54   // q-th quantile of a data set:
55   // value where q fraction of data is below and (1-q) fraction is above this value
56   // Xq = (1 - r) * X_NI1 + r * X_NI2
57   //   NI1 = (int) (q * (n+1))
58   //   NI2 = NI1 + 1
59   //   r = q * (n+1) - (int) (q * (n+1))
60   // (indices of X: 1...n)
61 
62   // sort the values first
63   QList<double> _values = values;
64   std::sort( _values.begin(), _values.end() );
65 
66   QList<double> breaks;
67 
68   // If there are no values to process: bail out
69   if ( _values.isEmpty() )
70     return QList<double>();
71 
72   const int n = _values.count();
73   double Xq = n > 0 ? _values[0] : 0.0;
74 
75   breaks.reserve( nclasses );
76   for ( int i = 1; i < nclasses; i++ )
77   {
78     if ( n > 1 )
79     {
80       const double q = i  / static_cast< double >( nclasses );
81       const double a = q * ( n - 1 );
82       const int aa = static_cast<  int >( a );
83 
84       const double r = a - aa;
85       Xq = ( 1 - r ) * _values[aa] + r * _values[aa + 1];
86     }
87     breaks.append( Xq );
88   }
89 
90   breaks.append( _values[ n - 1 ] );
91 
92   return breaks;
93 }
94 
95