@@ -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 ),
@@ -540,7 +545,6 @@ static QList<double> _calcJenksBreaks( QList<double> values, int classes,
540
545
double minimum, double maximum,
541
546
int maximumSize = 1000 )
542
547
{
543
-
544
548
// Jenks Optimal (Natural Breaks) algorithm
545
549
// Based on the Jenks algorithm from the 'classInt' package available for
546
550
// the R statistical prgramming language, and from Python code from here:
@@ -551,132 +555,121 @@ static QList<double> _calcJenksBreaks( QList<double> values, int classes,
551
555
// Returns class breaks such that classes are internally homogeneous while
552
556
// assuring heterogeneity among classes.
553
557
554
- QList<double > breaks;
555
558
if ( classes < 1 )
556
559
{
557
- breaks.append ( maximum );
558
- return breaks;
560
+ return QList<double >() << maximum;
559
561
}
560
562
561
- int n = values.count ();
562
- if ( classes >= n )
563
+ if ( classes >= values.size () )
563
564
{
564
565
return values;
565
566
}
566
567
567
- QList <double > sample;
568
+ QVector <double > sample;
568
569
569
570
// if we have lots of values, we need to take a random sample
570
- if ( n > maximumSize )
571
+ if ( values. size () > maximumSize )
571
572
{
572
573
// for now, sample at least maximumSize values or a 10% sample, whichever
573
574
// is larger. This will produce a more representative sample for very large
574
575
// 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++ )
580
587
{
581
588
// 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 ];
584
592
}
585
593
}
586
594
else
587
595
{
588
- sample = values;
596
+ sample = values. toVector () ;
589
597
}
590
- // sort the values
591
- qSort ( sample );
592
598
593
- QList< QList<double > > matrixOne;
594
- QList< QList<double > > matrixTwo;
599
+ int n = sample.size ();
600
+
601
+ // sort the sample values
602
+ qSort ( sample );
595
603
596
- double v, s1, s2, w, i3, i4, val;
604
+ QVector< QVector<int > > matrixOne ( n + 1 );
605
+ QVector< QVector<double > > matrixTwo ( n + 1 );
597
606
598
- for ( int i = 0 ; i < n + 1 ; i++ )
607
+ for ( int i = 0 ; i <= n ; i++ )
599
608
{
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 );
609
611
}
610
612
611
- for ( int i = 1 ; i < classes + 1 ; i++ )
613
+ for ( int i = 1 ; i <= classes; i++ )
612
614
{
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++ )
616
619
{
617
- matrixTwo[j][i] = std::numeric_limits<qreal >::max ();
620
+ matrixTwo[j][i] = std::numeric_limits<double >::max ();
618
621
}
619
622
}
620
623
621
- v = 0.0 ;
622
- for ( int l = 2 ; l < n + 1 ; l++ )
624
+ for ( int l = 2 ; l <= n; l++ )
623
625
{
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++ )
628
633
{
629
- i3 = l - m + 1 ;
634
+ int i3 = l - m + 1 ;
630
635
631
- val = sample[ i3 - 1 ];
636
+ double val = sample[ i3 - 1 ];
632
637
633
638
s2 += val * val;
634
639
s1 += val;
640
+ w++;
635
641
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 )
641
645
{
642
- for ( int j = 2 ; j < classes + 1 ; j++ )
646
+ for ( int j = 2 ; j <= classes; j++ )
643
647
{
644
648
if ( matrixTwo[l][j] >= v + matrixTwo[i4][j - 1 ] )
645
649
{
646
- matrixOne[l][j] = i3 ;
650
+ matrixOne[l][j] = i4 ;
647
651
matrixTwo[l][j] = v + matrixTwo[i4][j - 1 ];
648
652
}
649
653
}
650
654
}
651
655
}
652
- matrixOne[l][1 ] = 1.0 ;
656
+ matrixOne[l][1 ] = 1 ;
653
657
matrixTwo[l][1 ] = v;
654
658
}
655
659
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 ];
663
662
664
- int k = n;
665
- int count = classes;
666
- while ( count >= 2 )
663
+ for ( int j = classes, k = n; j >= 2 ; j-- )
667
664
{
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 ;
672
668
}
673
669
674
- return breaks;
670
+ return breaks. toList () ;
675
671
} // _calcJenksBreaks
676
672
677
- #include " qgsvectordataprovider.h"
678
- #include " qgsvectorcolorrampv2.h"
679
-
680
673
QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer (
681
674
QgsVectorLayer* vlayer,
682
675
QString attrName,
0 commit comments