@@ -20,6 +20,7 @@ qgsgraduatedsymbolrendererv2.cpp - Graduated Symbol Renderer Version 2
20
20
#include " qgsfeature.h"
21
21
#include " qgsvectorlayer.h"
22
22
#include " qgslogger.h"
23
+ #include " qgsvectordataprovider.h"
23
24
24
25
#include < QDomDocument>
25
26
#include < QDomElement>
@@ -28,12 +29,17 @@ qgsgraduatedsymbolrendererv2.cpp - Graduated Symbol Renderer Version 2
28
29
#include < cmath> // for pretty classification
29
30
30
31
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 )
32
36
{
33
37
}
34
38
35
39
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 )
37
43
{
38
44
mSymbol = range.mSymbol ->clone ();
39
45
}
@@ -93,7 +99,6 @@ QString QgsRendererRangeV2::dump()
93
99
94
100
// /////////
95
101
96
-
97
102
QgsGraduatedSymbolRendererV2::QgsGraduatedSymbolRendererV2 ( QString attrName, QgsRangeList ranges )
98
103
: QgsFeatureRendererV2( " graduatedSymbol" ),
99
104
mAttrName( attrName ),
@@ -560,7 +565,6 @@ static QList<double> _calcJenksBreaks( QList<double> values, int classes,
560
565
double minimum, double maximum,
561
566
int maximumSize = 1000 )
562
567
{
563
-
564
568
// Jenks Optimal (Natural Breaks) algorithm
565
569
// Based on the Jenks algorithm from the 'classInt' package available for
566
570
// the R statistical prgramming language, and from Python code from here:
@@ -571,131 +575,121 @@ static QList<double> _calcJenksBreaks( QList<double> values, int classes,
571
575
// Returns class breaks such that classes are internally homogeneous while
572
576
// assuring heterogeneity among classes.
573
577
574
- QList<double > breaks;
575
578
if ( classes <= 1 )
576
579
{
577
- breaks.append ( maximum );
578
- return breaks;
580
+ return QList<double >() << maximum;
579
581
}
580
582
581
- int n = values.count ();
582
- if ( classes >= n )
583
+ if ( classes >= values.size () )
583
584
{
584
585
return values;
585
586
}
586
587
587
- QList <double > sample;
588
+ QVector <double > sample;
588
589
589
590
// if we have lots of values, we need to take a random sample
590
- if ( n > maximumSize )
591
+ if ( values. size () > maximumSize )
591
592
{
592
593
// for now, sample at least maximumSize values or a 10% sample, whichever
593
594
// is larger. This will produce a more representative sample for very large
594
595
// layers, but could end up being computationally intensive...
595
- n = qMax ( maximumSize, ( int )(( double ) n * 0.10 ) );
596
- QgsDebugMsg ( QString ( " natural breaks (jenks) sample size: %1" ).arg ( n ) );
597
- sample.append ( minimum );
598
- sample.append ( maximum );
599
- for ( int i = 0 ; i < n - 2 ; i++ )
596
+
597
+ qsrand ( time ( 0 ) );
598
+
599
+ sample.resize ( qMax ( maximumSize, values.size () / 10 ) );
600
+
601
+ QgsDebugMsg ( QString ( " natural breaks (jenks) sample size: %1" ).arg ( sample.size () ) );
602
+ QgsDebugMsg ( QString ( " values:%1" ).arg ( values.size () ) );
603
+
604
+ sample[ 0 ] = minimum;
605
+ sample[ 1 ] = maximum;;
606
+ for ( int i = 2 ; i < sample.size (); i++ )
600
607
{
601
608
// pick a random integer from 0 to n
602
- int c = ( int )(( double ) rand () / (( double ) RAND_MAX + 1 ) * n - 1 );
603
- sample.append ( values[i+c] );
609
+ double r = qrand ();
610
+ int j = floor ( r / RAND_MAX * ( values.size () - 1 ) );
611
+ sample[ i ] = values[ j ];
604
612
}
605
613
}
606
614
else
607
615
{
608
- sample = values;
616
+ sample = values. toVector () ;
609
617
}
610
- // sort the values
611
- qSort ( sample );
612
618
613
- QList< QList<double > > matrixOne;
614
- QList< QList<double > > matrixTwo;
619
+ int n = sample.size ();
620
+
621
+ // sort the sample values
622
+ qSort ( sample );
615
623
616
- double v, s1, s2, w, i3, i4, val;
624
+ QVector< QVector<int > > matrixOne ( n + 1 );
625
+ QVector< QVector<double > > matrixTwo ( n + 1 );
617
626
618
- for ( int i = 0 ; i < n + 1 ; i++ )
627
+ for ( int i = 0 ; i <= n ; i++ )
619
628
{
620
- QList<double > tempOne;
621
- QList<double > tempTwo;
622
- for ( int j = 0 ; j < classes + 1 ; j++ )
623
- {
624
- tempOne.append ( 0.0 );
625
- tempTwo.append ( 0.0 );
626
- }
627
- matrixOne.append ( tempOne );
628
- matrixTwo.append ( tempTwo );
629
+ matrixOne[i].resize ( classes + 1 );
630
+ matrixTwo[i].resize ( classes + 1 );
629
631
}
630
632
631
- for ( int i = 1 ; i < classes + 1 ; i++ )
633
+ for ( int i = 1 ; i <= classes; i++ )
632
634
{
633
- matrixOne[1 ][i] = 1.0 ;
634
- matrixTwo[1 ][i] = 0.0 ;
635
- for ( int j = 2 ; j < n + 1 ; j++ )
635
+ matrixOne[0 ][i] = 1 ;
636
+ matrixOne[1 ][i] = 1 ;
637
+ matrixTwo[0 ][i] = 0.0 ;
638
+ for ( int j = 2 ; j <= n; j++ )
636
639
{
637
- matrixTwo[j][i] = std::numeric_limits<qreal >::max ();
640
+ matrixTwo[j][i] = std::numeric_limits<double >::max ();
638
641
}
639
642
}
640
643
641
- v = 0.0 ;
642
- for ( int l = 2 ; l < n + 1 ; l++ )
644
+ for ( int l = 2 ; l <= n; l++ )
643
645
{
644
- s1 = 0.0 ;
645
- s2 = 0.0 ;
646
- w = 0.0 ;
647
- for ( int m = 1 ; m < l + 1 ; m++ )
646
+ double s1 = 0.0 ;
647
+ double s2 = 0.0 ;
648
+ int w = 0 ;
649
+
650
+ double v = 0.0 ;
651
+
652
+ for ( int m = 1 ; m <= l; m++ )
648
653
{
649
- i3 = l - m + 1 ;
654
+ int i3 = l - m + 1 ;
650
655
651
- val = sample[ i3 - 1 ];
656
+ double val = sample[ i3 - 1 ];
652
657
653
658
s2 += val * val;
654
659
s1 += val;
660
+ w++;
655
661
656
- w += 1.0 ;
657
- v = s2 - ( s1 * s1 ) / w;
658
- i4 = i3 - 1 ;
659
-
660
- if ( i4 != 0.0 )
662
+ v = s2 - ( s1 * s1 ) / ( double ) w;
663
+ int i4 = i3 - 1 ;
664
+ if ( i4 != 0 )
661
665
{
662
- for ( int j = 2 ; j < classes + 1 ; j++ )
666
+ for ( int j = 2 ; j <= classes; j++ )
663
667
{
664
668
if ( matrixTwo[l][j] >= v + matrixTwo[i4][j - 1 ] )
665
669
{
666
- matrixOne[l][j] = i3 ;
670
+ matrixOne[l][j] = i4 ;
667
671
matrixTwo[l][j] = v + matrixTwo[i4][j - 1 ];
668
672
}
669
673
}
670
674
}
671
675
}
672
- matrixOne[l][1 ] = 1.0 ;
676
+ matrixOne[l][1 ] = 1 ;
673
677
matrixTwo[l][1 ] = v;
674
678
}
675
679
676
- for ( int i = 0 ; i < classes; i++ )
677
- {
678
- breaks.append ( 0.0 );
679
- }
680
-
681
- breaks[classes - 1 ] = sample[sample.size () - 1 ];
682
- // breaks[0] = values[0];
680
+ QVector<double > breaks ( classes );
681
+ breaks[classes-1 ] = sample[n-1 ];
683
682
684
- int k = n;
685
- int count = classes;
686
- while ( count >= 2 )
683
+ for ( int j = classes, k = n; j >= 2 ; j-- )
687
684
{
688
- int id = matrixOne[k][count] - 2 ;
689
- breaks[count - 2 ] = sample[id];
690
- k = matrixOne[k][count] - 1 ;
691
- count -= 1 ;
685
+ int id = matrixOne[k][j] - 1 ;
686
+ breaks[j - 2 ] = sample[id];
687
+ k = matrixOne[k][j] - 1 ;
692
688
}
693
689
694
- return breaks;
690
+ return breaks. toList () ;
695
691
} // _calcJenksBreaks
696
692
697
- #include " qgsvectordataprovider.h"
698
- #include " qgsvectorcolorrampv2.h"
699
693
700
694
QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer (
701
695
QgsVectorLayer* vlayer,
0 commit comments