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;
82 if ( values.size() > mMaximumSize )
88 sample.resize( std::max( mMaximumSize, values.size() / 10 ) );
90 QgsDebugMsgLevel( QStringLiteral(
"natural breaks (jenks) sample size: %1" ).arg( sample.size() ), 2 );
93 sample[ 0 ] = minimum;
94 sample[ 1 ] = maximum;
96 for (
int i = 2; i < sample.size(); i++ )
100 #if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
101 double r = QRandomGenerator::global()->generate();
105 int j = std::floor( r / RAND_MAX * ( values.size() - 1 ) );
106 sample[ i ] = values[ j ];
111 sample = values.toVector();
114 int n = sample.size();
117 std::sort( sample.begin(), sample.end() );
119 QVector< QVector<int> > matrixOne( n + 1 );
120 QVector< QVector<double> > matrixTwo( n + 1 );
122 for (
int i = 0; i <= n; i++ )
124 matrixOne[i].resize( nclasses + 1 );
125 matrixTwo[i].resize( nclasses + 1 );
128 for (
int i = 1; i <= nclasses; i++ )
132 matrixTwo[0][i] = 0.0;
133 for (
int j = 2; j <= n; j++ )
135 matrixTwo[j][i] = std::numeric_limits<double>::max();
139 for (
int l = 2; l <= n; l++ )
147 for (
int m = 1; m <= l; m++ )
151 double val = sample[ i3 - 1 ];
157 v = s2 - ( s1 * s1 ) /
static_cast< double >( w );
161 for (
int j = 2; j <= nclasses; j++ )
163 if ( matrixTwo[l][j] >= v + matrixTwo[i4][j - 1] )
165 matrixOne[l][j] = i4;
166 matrixTwo[l][j] = v + matrixTwo[i4][j - 1];
175 QVector<double> breaks( nclasses );
176 breaks[nclasses - 1] = sample[n - 1];
178 for (
int j = nclasses, k = n; j >= 2; j-- )
180 int id = matrixOne[k][j] - 1;
181 breaks[j - 2] = sample[
id];
182 k = matrixOne[k][j] - 1;
185 return breaks.toList();