20 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
21 #include <QRandomGenerator>
32 return QObject::tr(
"Natural Breaks (Jenks)" );
37 return QStringLiteral(
"Jenks" );
53 QList<double> QgsClassificationJenks::calculateBreaks(
double &minimum,
double &maximum,
54 const QList<double> &values,
int nclasses )
66 if ( values.isEmpty() )
67 return QList<double>();
71 return QList<double>() << maximum;
74 if ( nclasses >= values.size() )
79 QVector<double> sample;
80 QVector<double> sorted;
83 if ( values.size() > mMaximumSize )
89 sample.resize( std::max( mMaximumSize,
static_cast<int>( values.size() ) / 10 ) );
91 QgsDebugMsgLevel( QStringLiteral(
"natural breaks (jenks) sample size: %1" ).arg( sample.size() ), 2 );
94 sample[ 0 ] = minimum;
95 sample[ 1 ] = maximum;
97 sorted = values.toVector();
98 std::sort( sorted.begin(), sorted.end() );
106 for (
int i = 1; i < sorted.size() - 2; i++ )
108 if ( ( i * ( mMaximumSize - 2 ) / ( sorted.size() - 2 ) ) > j )
111 sample[ j + 2 ] = sorted[ i ];
117 sample = values.toVector();
120 const int n = sample.size();
123 std::sort( sample.begin(), sample.end() );
125 QVector< QVector<int> > matrixOne( n + 1 );
126 QVector< QVector<double> > matrixTwo( n + 1 );
128 for (
int i = 0; i <= n; i++ )
130 matrixOne[i].resize( nclasses + 1 );
131 matrixTwo[i].resize( nclasses + 1 );
134 for (
int i = 1; i <= nclasses; i++ )
138 matrixTwo[0][i] = 0.0;
139 for (
int j = 2; j <= n; j++ )
141 matrixTwo[j][i] = std::numeric_limits<double>::max();
145 for (
int l = 2; l <= n; l++ )
153 for (
int m = 1; m <= l; m++ )
155 const int i3 = l - m + 1;
157 const double val = sample[ i3 - 1 ];
163 v = s2 - ( s1 * s1 ) /
static_cast< double >( w );
164 const int i4 = i3 - 1;
167 for (
int j = 2; j <= nclasses; j++ )
169 if ( matrixTwo[l][j] >= v + matrixTwo[i4][j - 1] )
171 matrixOne[l][j] = i4;
172 matrixTwo[l][j] = v + matrixTwo[i4][j - 1];
181 QVector<double> breaks( nclasses );
182 breaks[nclasses - 1] = sample[n - 1];
184 for (
int j = nclasses, k = n; j >= 2; j-- )
186 const int id = matrixOne[k][j] - 1;
187 breaks[j - 2] = sample[
id];
188 k = matrixOne[k][j] - 1;
191 return breaks.toList();