26 #include <QDomDocument>
27 #include <QDomElement>
34 : mLowerValue( 0 ), mUpperValue( 0 ), mSymbol( 0 ), mLabel()
39 : mLowerValue( lowerValue )
40 , mUpperValue( upperValue )
47 : mLowerValue( range.mLowerValue )
48 , mUpperValue( range.mUpperValue )
49 , mSymbol( range.mSymbol.data() ? range.mSymbol->clone() : NULL )
50 , mLabel( range.mLabel )
116 if ( !
mSymbol.data() || props.value(
"attribute",
"" ).isEmpty() )
119 QString attrName = props[
"attribute" ];
121 QDomElement ruleElem = doc.createElement(
"se:Rule" );
122 element.appendChild( ruleElem );
124 QDomElement nameElem = doc.createElement(
"se:Name" );
125 nameElem.appendChild( doc.createTextNode(
mLabel ) );
126 ruleElem.appendChild( nameElem );
128 QDomElement descrElem = doc.createElement(
"se:Description" );
129 QDomElement titleElem = doc.createElement(
"se:Title" );
131 titleElem.appendChild( doc.createTextNode( !
mLabel.isEmpty() ?
mLabel : descrStr ) );
132 descrElem.appendChild( titleElem );
133 ruleElem.appendChild( descrElem );
136 QString filterFunc = QString(
"%1 > %2 AND %1 <= %3" )
137 .arg( attrName.replace(
"\"",
"\"\"" ) )
141 mSymbol->toSld( doc, ruleElem, props );
148 mAttrName( attrName ),
151 mInvertedColorRamp( false ),
164 for ( QgsRangeList::iterator it =
mRanges.begin(); it !=
mRanges.end(); ++it )
166 if ( it->lowerValue() <= value && it->upperValue() >= value )
177 if ( mAttrNum < 0 || mAttrNum >= attrs.count() )
187 if ( value.isNull() )
192 if ( symbol == NULL )
199 const double rotation =
mRotation.data() ?
mRotation->evaluate( feature ).toDouble() : 0;
210 markerSymbol->
setSize( sizeScale * static_cast<QgsMarkerSymbolV2*>( symbol )->
size() );
216 lineSymbol->
setWidth( sizeScale * static_cast<QgsLineSymbolV2*>( symbol )->width() );
232 QgsRangeList::iterator it =
mRanges.begin();
233 for ( ; it !=
mRanges.end(); ++it )
235 it->symbol()->startRender( context, vlayer );
250 QgsRangeList::iterator it =
mRanges.begin();
251 for ( ; it !=
mRanges.end(); ++it )
252 it->symbol()->stopRender( context );
255 QHash<QgsSymbolV2*, QgsSymbolV2*>::iterator it2 =
mTempSymbols.begin();
258 it2.value()->stopRender( context );
266 QSet<QString> attributes;
270 attributes.unite( exp->referencedColumns().toSet() );
277 QgsRangeList::const_iterator range_it =
mRanges.constBegin();
278 for ( ; range_it !=
mRanges.constEnd(); ++range_it )
286 return attributes.toList();
291 if ( rangeIndex < 0 || rangeIndex >=
mRanges.size() )
293 mRanges[rangeIndex].setSymbol( symbol );
299 if ( rangeIndex < 0 || rangeIndex >=
mRanges.size() )
301 mRanges[rangeIndex].setLabel( label );
307 if ( rangeIndex < 0 || rangeIndex >=
mRanges.size() )
309 mRanges[rangeIndex].setUpperValue( value );
315 if ( rangeIndex < 0 || rangeIndex >=
mRanges.size() )
317 mRanges[rangeIndex].setLowerValue( value );
323 QString s = QString(
"GRADUATED: attr %1\n" ).arg(
mAttrName );
324 for (
int i = 0; i <
mRanges.count(); i++ )
352 props[
"angle" ] =
mRotation->expression();
357 for ( QgsRangeList::const_iterator it =
mRanges.constBegin(); it !=
mRanges.constEnd(); ++it )
360 it->toSld( doc, element, catProps );
367 for (
int i = 0; i <
mRanges.count(); i++ )
368 lst.append(
mRanges[i].symbol() );
380 double step = ( maximum - minimum ) / classes;
382 QList<double> breaks;
383 double value = minimum;
384 for (
int i = 0; i < classes; i++ )
387 breaks.append( value );
392 breaks[classes-1] = maximum;
410 QList<double> breaks;
413 if ( !values.count() )
416 int n = values.count();
417 double Xq = n > 0 ? values[0] : 0.0;
419 for (
int i = 1; i < classes; i++ )
423 double q = i / ( double ) classes;
424 double a = q * ( n - 1 );
425 int aa = ( int )( a );
428 Xq = ( 1 - r ) * values[aa] + r * values[aa+1];
433 breaks.append( values[ n-1 ] );
450 QList<double> breaks;
453 breaks.append( maximum );
457 int minimumCount = ( int ) classes / 3;
458 double shrink = 0.75;
459 double highBias = 1.5;
460 double adjustBias = 0.5 + 1.5 * highBias;
461 int divisions = classes;
466 double dx = maximum - minimum;
468 if ( dx == 0 && maximum == 0 )
476 cell = qMax( qAbs( minimum ), qAbs( maximum ) );
477 if ( adjustBias >= 1.5 * h + 0.5 )
479 U = 1 + ( 1.0 / ( 1 + h ) );
483 U = 1 + ( 1.5 / ( 1 + adjustBias ) );
485 small = dx < ( cell * U * qMax( 1, divisions ) * 1e-07 * 3.0 );
492 cell = 9 + cell / 10;
493 cell = cell * shrink;
495 if ( minimumCount > 1 )
497 cell = cell / minimumCount;
505 cell = cell / divisions;
508 if ( cell < 20 * 1e-07 )
513 double base = pow( 10.0, floor( log10( cell ) ) );
515 if (( 2 * base ) - cell < h *( cell - unit ) )
518 if (( 5 * base ) - cell < adjustBias *( cell - unit ) )
521 if (( 10.0 * base ) - cell < h *( cell - unit ) )
528 int start = floor( minimum / unit + 1e-07 );
529 int end = ceil( maximum / unit - 1e-07 );
532 while ( start * unit > minimum + ( 1e-07 * unit ) )
536 while ( end * unit < maximum - ( 1e-07 * unit ) )
540 QgsDebugMsg( QString(
"pretty classes: %1" ).arg( end ) );
544 int k = floor( 0.5 + end - start );
545 if ( k < minimumCount )
547 k = minimumCount - k;
551 start = start - k / 2 + k % 2;
555 start = start - k / 2;
556 end = end + k / 2 + k % 2;
559 double minimumBreak = start * unit;
561 int count = end - start;
563 for (
int i = 1; i < count + 1; i++ )
565 breaks.append( minimumBreak + i * unit );
568 if ( breaks.isEmpty() )
571 if ( breaks.first() < minimum )
575 if ( breaks.last() > maximum )
577 breaks[breaks.count()-1] = maximum;
595 if ( !values.count() )
596 return QList<double>();
600 int n = values.count();
601 double minimum = values[0];
602 double maximum = values[0];
604 for (
int i = 0; i < n; i++ )
607 minimum = qMin( values[i], minimum );
608 maximum = qMax( values[i], maximum );
610 mean = mean / ( double ) n;
613 for (
int i = 0; i < n; i++ )
615 sd = values[i] - mean;
618 stdDev = sqrt( stdDev / n );
620 QList<double> breaks =
_calcPrettyBreaks(( minimum - mean ) / stdDev, ( maximum - mean ) / stdDev, classes );
621 for (
int i = 0; i < breaks.count(); i++ )
623 labels.append((
int ) breaks[i] );
624 breaks[i] = ( breaks[i] * stdDev ) + mean;
631 double minimum,
double maximum,
632 int maximumSize = 1000 )
644 if ( !values.count() )
645 return QList<double>();
649 return QList<double>() << maximum;
652 if ( classes >= values.size() )
657 QVector<double> sample;
660 if ( values.size() > maximumSize )
668 sample.resize( qMax( maximumSize, values.size() / 10 ) );
670 QgsDebugMsg( QString(
"natural breaks (jenks) sample size: %1" ).arg( sample.size() ) );
671 QgsDebugMsg( QString(
"values:%1" ).arg( values.size() ) );
673 sample[ 0 ] = minimum;
674 sample[ 1 ] = maximum;;
675 for (
int i = 2; i < sample.size(); i++ )
679 int j = floor( r / RAND_MAX * ( values.size() - 1 ) );
680 sample[ i ] = values[ j ];
685 sample = values.toVector();
688 int n = sample.size();
693 QVector< QVector<int> > matrixOne( n + 1 );
694 QVector< QVector<double> > matrixTwo( n + 1 );
696 for (
int i = 0; i <= n; i++ )
698 matrixOne[i].resize( classes + 1 );
699 matrixTwo[i].resize( classes + 1 );
702 for (
int i = 1; i <= classes; i++ )
706 matrixTwo[0][i] = 0.0;
707 for (
int j = 2; j <= n; j++ )
713 for (
int l = 2; l <= n; l++ )
721 for (
int m = 1; m <= l; m++ )
725 double val = sample[ i3 - 1 ];
731 v = s2 - ( s1 * s1 ) / (
double ) w;
735 for (
int j = 2; j <= classes; j++ )
737 if ( matrixTwo[l][j] >= v + matrixTwo[i4][j - 1] )
739 matrixOne[l][j] = i4;
740 matrixTwo[l][j] = v + matrixTwo[i4][j - 1];
749 QVector<double> breaks( classes );
750 breaks[classes-1] = sample[n-1];
752 for (
int j = classes, k = n; j >= 2; j-- )
754 int id = matrixOne[k][j] - 1;
755 breaks[j - 2] = sample[id];
756 k = matrixOne[k][j] - 1;
759 return breaks.toList();
779 QScopedPointer<QgsExpression> expression;
785 if ( expression->hasParserError() || !expression->prepare( vlayer->
pendingFields() ) )
788 QList<double> values;
793 values << expression->evaluate( feature ).toDouble();
796 minimum = values.first();
797 maximum = values.last();
805 QgsDebugMsg( QString(
"min %1 // max %2" ).arg( minimum ).arg( maximum ) );
806 QList<double> breaks;
812 else if ( mode ==
Pretty )
819 QList<double> values;
822 if ( expression.isNull() )
823 lst.append( attrName );
825 lst = expression->referencedColumns();
832 QVariant v = expression.isNull() ? f.
attribute( attrNum ) : expression->evaluate( f );
834 values.append( v.toDouble() );
842 else if ( mode ==
Jenks )
846 else if ( mode ==
StdDev )
857 double lower, upper = minimum;
862 for ( QList<double>::iterator it = breaks.begin(); it != breaks.end(); ++it, ++i )
870 label =
"< " + QString::number( labels[i],
'i', 0 ) +
" Std Dev";
872 else if ( i == labels.count() - 1 )
874 label =
">= " + QString::number( labels[i-1],
'i', 0 ) +
" Std Dev";
878 label = QString::number( labels[i-1],
'i', 0 ) +
" Std Dev" +
" - " + QString::number( labels[i],
'i', 0 ) +
" Std Dev";
883 label = QString::number( lower,
'f', 4 ) +
" - " + QString::number( upper,
'f', 4 );
888 if ( inverted ) colorValue = ( breaks.count() > 1 ? ( double )( breaks.count() - i - 1 ) / ( breaks.count() - 1 ) : 0 );
889 else colorValue = ( breaks.count() > 1 ? ( double ) i / ( breaks.count() - 1 ) : 0 );
905 QDomElement symbolsElem = element.firstChildElement(
"symbols" );
906 if ( symbolsElem.isNull() )
909 QDomElement rangesElem = element.firstChildElement(
"ranges" );
910 if ( rangesElem.isNull() )
916 QDomElement rangeElem = rangesElem.firstChildElement();
917 while ( !rangeElem.isNull() )
919 if ( rangeElem.tagName() ==
"range" )
921 double lowerValue = rangeElem.attribute(
"lower" ).toDouble();
922 double upperValue = rangeElem.attribute(
"upper" ).toDouble();
923 QString symbolName = rangeElem.attribute(
"symbol" );
924 QString label = rangeElem.attribute(
"label" );
925 if ( symbolMap.contains( symbolName ) )
927 QgsSymbolV2* symbol = symbolMap.take( symbolName );
931 rangeElem = rangeElem.nextSiblingElement();
934 QString attrName = element.attribute(
"attr" );
942 QDomElement sourceSymbolElem = element.firstChildElement(
"source-symbol" );
943 if ( !sourceSymbolElem.isNull() )
946 if ( sourceSymbolMap.contains(
"0" ) )
954 QDomElement sourceColorRampElem = element.firstChildElement(
"colorramp" );
955 if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute(
"name" ) ==
"[source]" )
958 QDomElement invertedColorRampElem = element.firstChildElement(
"invertedcolorramp" );
959 if ( !invertedColorRampElem.isNull() )
964 QDomElement modeElem = element.firstChildElement(
"mode" );
965 if ( !modeElem.isNull() )
967 QString modeString = modeElem.attribute(
"name" );
968 if ( modeString ==
"equal" )
970 else if ( modeString ==
"quantile" )
972 else if ( modeString ==
"jenks" )
974 else if ( modeString ==
"stddev" )
976 else if ( modeString ==
"pretty" )
980 QDomElement rotationElem = element.firstChildElement(
"rotation" );
981 if ( !rotationElem.isNull() )
984 QDomElement sizeScaleElem = element.firstChildElement(
"sizescale" );
985 if ( !sizeScaleElem.isNull() )
996 rendererElem.setAttribute(
"type",
"graduatedSymbol" );
998 rendererElem.setAttribute(
"attr",
mAttrName );
1003 QDomElement rangesElem = doc.createElement(
"ranges" );
1004 QgsRangeList::const_iterator it =
mRanges.constBegin();
1005 for ( ; it !=
mRanges.constEnd(); ++it )
1008 QString symbolName = QString::number( i );
1009 symbols.insert( symbolName, range.
symbol() );
1011 QDomElement rangeElem = doc.createElement(
"range" );
1012 rangeElem.setAttribute(
"lower", QString::number( range.
lowerValue(),
'f' ) );
1013 rangeElem.setAttribute(
"upper", QString::number( range.
upperValue(),
'f' ) );
1014 rangeElem.setAttribute(
"symbol", symbolName );
1015 rangeElem.setAttribute(
"label", range.
label() );
1016 rangesElem.appendChild( rangeElem );
1020 rendererElem.appendChild( rangesElem );
1024 rendererElem.appendChild( symbolsElem );
1032 rendererElem.appendChild( sourceSymbolElem );
1039 rendererElem.appendChild( colorRampElem );
1040 QDomElement invertedElem = doc.createElement(
"invertedcolorramp" );
1042 rendererElem.appendChild( invertedElem );
1048 modeString =
"equal";
1050 modeString =
"quantile";
1052 modeString =
"jenks";
1054 modeString =
"stddev";
1056 modeString =
"pretty";
1057 if ( !modeString.isEmpty() )
1059 QDomElement modeElem = doc.createElement(
"mode" );
1060 modeElem.setAttribute(
"name", modeString );
1061 rendererElem.appendChild( modeElem );
1064 QDomElement rotationElem = doc.createElement(
"rotation" );
1067 rendererElem.appendChild( rotationElem );
1069 QDomElement sizeScaleElem = doc.createElement(
"sizescale" );
1073 rendererElem.appendChild( sizeScaleElem );
1075 return rendererElem;
1081 bool showClassifiers = settings.value(
"/qgis/showLegendClassifiers",
false ).toBool();
1084 if ( showClassifiers )
1089 int count =
ranges().count();
1090 for (
int i = 0; i < count; i++ )
1094 lst << qMakePair( range.
label(), pix );
1101 Q_UNUSED( scaleDenominator );
1103 bool showClassifiers = settings.value(
"/qgis/showLegendClassifiers",
false ).toBool();
1106 if ( showClassifiers )
1113 if ( rule.isEmpty() || range.
label() == rule )
1124 lst << qMakePair( range.
label(), symbol );
1156 if ( inverted ) colorValue = (
mRanges.count() > 1 ? ( double )(
mRanges.count() - i - 1 ) / (
mRanges.count() - 1 ) : 0 );
1157 else colorValue = (
mRanges.count() > 1 ? ( double ) i / (
mRanges.count() - 1 ) : 0 );
1202 for ( QgsRangeList::iterator it =
mRanges.begin(); it !=
mRanges.end(); ++it )
1211 QString label =
"0.0 - 0.0";
1233 if ( from < 0 || from >=
mRanges.size() || to < 0 || to >=
mRanges.size() )
return;
1250 if ( order == Qt::AscendingOrder )
1262 return QString::localeAwareCompare( r1.
label(), r2.
label() ) < 0;
1272 if ( order == Qt::AscendingOrder )