Skip to content

Commit 0241379

Browse files
committedDec 24, 2011
fix #3963
1 parent 36f9037 commit 0241379

File tree

1 file changed

+66
-72
lines changed

1 file changed

+66
-72
lines changed
 

‎src/core/symbology-ng/qgsgraduatedsymbolrendererv2.cpp

Lines changed: 66 additions & 72 deletions
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 ),
@@ -560,7 +565,6 @@ static QList<double> _calcJenksBreaks( QList<double> values, int classes,
560565
double minimum, double maximum,
561566
int maximumSize = 1000 )
562567
{
563-
564568
// Jenks Optimal (Natural Breaks) algorithm
565569
// Based on the Jenks algorithm from the 'classInt' package available for
566570
// the R statistical prgramming language, and from Python code from here:
@@ -571,131 +575,121 @@ static QList<double> _calcJenksBreaks( QList<double> values, int classes,
571575
// Returns class breaks such that classes are internally homogeneous while
572576
// assuring heterogeneity among classes.
573577

574-
QList<double> breaks;
575578
if ( classes <= 1 )
576579
{
577-
breaks.append( maximum );
578-
return breaks;
580+
return QList<double>() << maximum;
579581
}
580582

581-
int n = values.count();
582-
if ( classes >= n )
583+
if ( classes >= values.size() )
583584
{
584585
return values;
585586
}
586587

587-
QList<double> sample;
588+
QVector<double> sample;
588589

589590
// if we have lots of values, we need to take a random sample
590-
if ( n > maximumSize )
591+
if ( values.size() > maximumSize )
591592
{
592593
// for now, sample at least maximumSize values or a 10% sample, whichever
593594
// is larger. This will produce a more representative sample for very large
594595
// 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++ )
600607
{
601608
// 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 ];
604612
}
605613
}
606614
else
607615
{
608-
sample = values;
616+
sample = values.toVector();
609617
}
610-
// sort the values
611-
qSort( sample );
612618

613-
QList< QList<double> > matrixOne;
614-
QList< QList<double> > matrixTwo;
619+
int n = sample.size();
620+
621+
// sort the sample values
622+
qSort( sample );
615623

616-
double v, s1, s2, w, i3, i4, val;
624+
QVector< QVector<int> > matrixOne( n + 1 );
625+
QVector< QVector<double> > matrixTwo( n + 1 );
617626

618-
for ( int i = 0; i < n + 1; i++ )
627+
for ( int i = 0; i <= n; i++ )
619628
{
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 );
629631
}
630632

631-
for ( int i = 1; i < classes + 1; i++ )
633+
for ( int i = 1; i <= classes; i++ )
632634
{
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++ )
636639
{
637-
matrixTwo[j][i] = std::numeric_limits<qreal>::max();
640+
matrixTwo[j][i] = std::numeric_limits<double>::max();
638641
}
639642
}
640643

641-
v = 0.0;
642-
for ( int l = 2; l < n + 1; l++ )
644+
for ( int l = 2; l <= n; l++ )
643645
{
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++ )
648653
{
649-
i3 = l - m + 1;
654+
int i3 = l - m + 1;
650655

651-
val = sample[ i3 - 1 ];
656+
double val = sample[ i3 - 1 ];
652657

653658
s2 += val * val;
654659
s1 += val;
660+
w++;
655661

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 )
661665
{
662-
for ( int j = 2; j < classes + 1; j++ )
666+
for ( int j = 2; j <= classes; j++ )
663667
{
664668
if ( matrixTwo[l][j] >= v + matrixTwo[i4][j - 1] )
665669
{
666-
matrixOne[l][j] = i3;
670+
matrixOne[l][j] = i4;
667671
matrixTwo[l][j] = v + matrixTwo[i4][j - 1];
668672
}
669673
}
670674
}
671675
}
672-
matrixOne[l][1] = 1.0;
676+
matrixOne[l][1] = 1;
673677
matrixTwo[l][1] = v;
674678
}
675679

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];
683682

684-
int k = n;
685-
int count = classes;
686-
while ( count >= 2 )
683+
for ( int j = classes, k = n; j >= 2; j-- )
687684
{
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;
692688
}
693689

694-
return breaks;
690+
return breaks.toList();
695691
} //_calcJenksBreaks
696692

697-
#include "qgsvectordataprovider.h"
698-
#include "qgsvectorcolorrampv2.h"
699693

700694
QgsGraduatedSymbolRendererV2* QgsGraduatedSymbolRendererV2::createRenderer(
701695
QgsVectorLayer* vlayer,

0 commit comments

Comments
 (0)
Please sign in to comment.