Skip to content

Commit 78379f6

Browse files
jef-nalexbruy
authored andcommitted
fix #3963
1 parent 07c7b5a commit 78379f6

File tree

1 file changed

+66
-73
lines changed

1 file changed

+66
-73
lines changed

src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp

+66-73
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ qgsgraduatedsymbolrendererv2.cpp - Graduated Symbol Renderer Version 2
2020
#include "qgsfeature.h"
2121
#include "qgsvectorlayer.h"
2222
#include "qgslogger.h"
23+
#include "qgsvectordataprovider.h"
2324

2425
#include <QDomDocument>
2526
#include <QDomElement>
@@ -28,12 +29,17 @@ qgsgraduatedsymbolrendererv2.cpp - Graduated Symbol Renderer Version 2
2829
#include <cmath> // for pretty classification
2930

3031
QgsRendererRangeV2::QgsRendererRangeV2( double lowerValue, double upperValue, QgsSymbolV2* symbol, QString label )
31-
: mLowerValue( lowerValue ), mUpperValue( upperValue ), mSymbol( symbol ), mLabel( label )
32+
: mLowerValue( lowerValue )
33+
, mUpperValue( upperValue )
34+
, mSymbol( symbol )
35+
, mLabel( label )
3236
{
3337
}
3438

3539
QgsRendererRangeV2::QgsRendererRangeV2( const QgsRendererRangeV2& range )
36-
: mLowerValue( range.mLowerValue ), mUpperValue( range.mUpperValue ), mLabel( range.mLabel )
40+
: mLowerValue( range.mLowerValue )
41+
, mUpperValue( range.mUpperValue )
42+
, mLabel( range.mLabel )
3743
{
3844
mSymbol = range.mSymbol->clone();
3945
}
@@ -93,7 +99,6 @@ QString QgsRendererRangeV2::dump()
9399

94100
///////////
95101

96-
97102
QgsGraduatedSymbolRendererV2::QgsGraduatedSymbolRendererV2( QString attrName, QgsRangeList ranges )
98103
: QgsFeatureRendererV2( "graduatedSymbol" ),
99104
mAttrName( attrName ),
@@ -540,7 +545,6 @@ static QList<double> _calcJenksBreaks( QList<double> values, int classes,
540545
double minimum, double maximum,
541546
int maximumSize = 1000 )
542547
{
543-
544548
// Jenks Optimal (Natural Breaks) algorithm
545549
// Based on the Jenks algorithm from the 'classInt' package available for
546550
// the R statistical prgramming language, and from Python code from here:
@@ -551,132 +555,121 @@ static QList<double> _calcJenksBreaks( QList<double> values, int classes,
551555
// Returns class breaks such that classes are internally homogeneous while
552556
// assuring heterogeneity among classes.
553557

554-
QList<double> breaks;
555558
if ( classes < 1 )
556559
{
557-
breaks.append( maximum );
558-
return breaks;
560+
return QList<double>() << maximum;
559561
}
560562

561-
int n = values.count();
562-
if ( classes >= n )
563+
if ( classes >= values.size() )
563564
{
564565
return values;
565566
}
566567

567-
QList<double> sample;
568+
QVector<double> sample;
568569

569570
// if we have lots of values, we need to take a random sample
570-
if ( n > maximumSize )
571+
if ( values.size() > maximumSize )
571572
{
572573
// for now, sample at least maximumSize values or a 10% sample, whichever
573574
// is larger. This will produce a more representative sample for very large
574575
// layers, but could end up being computationally intensive...
575-
n = qMax( maximumSize, ( int )(( double ) n * 0.10 ) );
576-
QgsDebugMsg( QString( "natural breaks (jenks) sample size: %1" ).arg( n ) );
577-
sample.append( minimum );
578-
sample.append( maximum );
579-
for ( int i = 0; i < n - 2; i++ )
576+
577+
qsrand( time( 0 ) );
578+
579+
sample.resize( qMax( maximumSize, values.size() / 10 ) );
580+
581+
QgsDebugMsg( QString( "natural breaks (jenks) sample size: %1" ).arg( sample.size() ) );
582+
QgsDebugMsg( QString( "values:%1" ).arg( values.size() ) );
583+
584+
sample[ 0 ] = minimum;
585+
sample[ 1 ] = maximum;;
586+
for ( int i = 2; i < sample.size(); i++ )
580587
{
581588
// pick a random integer from 0 to n
582-
int c = ( int )(( double ) rand() / (( double ) RAND_MAX + 1 ) * n - 1 );
583-
sample.append( values[i+c] );
589+
double r = qrand();
590+
int j = floor( r / RAND_MAX * ( values.size() - 1 ) );
591+
sample[ i ] = values[ j ];
584592
}
585593
}
586594
else
587595
{
588-
sample = values;
596+
sample = values.toVector();
589597
}
590-
// sort the values
591-
qSort( sample );
592598

593-
QList< QList<double> > matrixOne;
594-
QList< QList<double> > matrixTwo;
599+
int n = sample.size();
600+
601+
// sort the sample values
602+
qSort( sample );
595603

596-
double v, s1, s2, w, i3, i4, val;
604+
QVector< QVector<int> > matrixOne( n + 1 );
605+
QVector< QVector<double> > matrixTwo( n + 1 );
597606

598-
for ( int i = 0; i < n + 1; i++ )
607+
for ( int i = 0; i <= n; i++ )
599608
{
600-
QList<double > tempOne;
601-
QList<double > tempTwo;
602-
for ( int j = 0; j < classes + 1; j++ )
603-
{
604-
tempOne.append( 0.0 );
605-
tempTwo.append( 0.0 );
606-
}
607-
matrixOne.append( tempOne );
608-
matrixTwo.append( tempTwo );
609+
matrixOne[i].resize( classes + 1 );
610+
matrixTwo[i].resize( classes + 1 );
609611
}
610612

611-
for ( int i = 1; i < classes + 1; i++ )
613+
for ( int i = 1; i <= classes; i++ )
612614
{
613-
matrixOne[1][i] = 1.0;
614-
matrixTwo[1][i] = 0.0;
615-
for ( int j = 2; j < n + 1; j++ )
615+
matrixOne[0][i] = 1;
616+
matrixOne[1][i] = 1;
617+
matrixTwo[0][i] = 0.0;
618+
for ( int j = 2; j <= n; j++ )
616619
{
617-
matrixTwo[j][i] = std::numeric_limits<qreal>::max();
620+
matrixTwo[j][i] = std::numeric_limits<double>::max();
618621
}
619622
}
620623

621-
v = 0.0;
622-
for ( int l = 2; l < n + 1; l++ )
624+
for ( int l = 2; l <= n; l++ )
623625
{
624-
s1 = 0.0;
625-
s2 = 0.0;
626-
w = 0.0;
627-
for ( int m = 1; m < l + 1; m++ )
626+
double s1 = 0.0;
627+
double s2 = 0.0;
628+
int w = 0;
629+
630+
double v = 0.0;
631+
632+
for ( int m = 1; m <= l; m++ )
628633
{
629-
i3 = l - m + 1;
634+
int i3 = l - m + 1;
630635

631-
val = sample[ i3 - 1 ];
636+
double val = sample[ i3 - 1 ];
632637

633638
s2 += val * val;
634639
s1 += val;
640+
w++;
635641

636-
w += 1.0;
637-
v = s2 - ( s1 * s1 ) / w;
638-
i4 = i3 - 1;
639-
640-
if ( i4 != 0.0 )
642+
v = s2 - ( s1 * s1 ) / ( double ) w;
643+
int i4 = i3 - 1;
644+
if ( i4 != 0 )
641645
{
642-
for ( int j = 2; j < classes + 1; j++ )
646+
for ( int j = 2; j <= classes; j++ )
643647
{
644648
if ( matrixTwo[l][j] >= v + matrixTwo[i4][j - 1] )
645649
{
646-
matrixOne[l][j] = i3;
650+
matrixOne[l][j] = i4;
647651
matrixTwo[l][j] = v + matrixTwo[i4][j - 1];
648652
}
649653
}
650654
}
651655
}
652-
matrixOne[l][1] = 1.0;
656+
matrixOne[l][1] = 1;
653657
matrixTwo[l][1] = v;
654658
}
655659

656-
for ( int i = 0; i < classes; i++ )
657-
{
658-
breaks.append( 0.0 );
659-
}
660-
661-
breaks[classes - 1] = sample[sample.size() - 1];
662-
// breaks[0] = values[0];
660+
QVector<double> breaks( classes );
661+
breaks[classes-1] = sample[n-1];
663662

664-
int k = n;
665-
int count = classes;
666-
while ( count >= 2 )
663+
for ( int j = classes, k = n; j >= 2; j-- )
667664
{
668-
int id = matrixOne[k][count] - 2;
669-
breaks[count - 2] = sample[id];
670-
k = matrixOne[k][count] - 1;
671-
count -= 1;
665+
int id = matrixOne[k][j] - 1;
666+
breaks[j - 2] = sample[id];
667+
k = matrixOne[k][j] - 1;
672668
}
673669

674-
return breaks;
670+
return breaks.toList();
675671
} //_calcJenksBreaks
676672

677-
#include "qgsvectordataprovider.h"
678-
#include "qgsvectorcolorrampv2.h"
679-
680673
QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer(
681674
QgsVectorLayer* vlayer,
682675
QString attrName,

0 commit comments

Comments
 (0)