38 #include <QDomDocument> 39 #include <QDomElement> 46 : mLowerValue( lowerValue )
47 , mUpperValue( upperValue )
143 if ( !
mSymbol || props.value( QStringLiteral(
"attribute" ), QString() ).isEmpty() )
146 QString attrName = props[ QStringLiteral(
"attribute" )];
148 QDomElement ruleElem = doc.createElement( QStringLiteral(
"se:Rule" ) );
149 element.appendChild( ruleElem );
151 QDomElement nameElem = doc.createElement( QStringLiteral(
"se:Name" ) );
152 nameElem.appendChild( doc.createTextNode(
mLabel ) );
153 ruleElem.appendChild( nameElem );
155 QDomElement descrElem = doc.createElement( QStringLiteral(
"se:Description" ) );
156 QDomElement titleElem = doc.createElement( QStringLiteral(
"se:Title" ) );
158 titleElem.appendChild( doc.createTextNode( !
mLabel.isEmpty() ?
mLabel : descrStr ) );
159 descrElem.appendChild( titleElem );
160 ruleElem.appendChild( descrElem );
163 QString filterFunc = QStringLiteral(
"\"%1\" %2 %3 AND \"%1\" <= %4" )
164 .arg( attrName.replace(
'\"', QLatin1String(
"\"\"" ) ),
165 firstRange ? QStringLiteral(
">=" ) : QStringLiteral(
">" ),
170 mSymbol->toSld( doc, ruleElem, props );
179 : mFormat( QStringLiteral(
"%1 - %2" ) )
180 , mReTrailingZeroes(
"[.,]?0*$" )
181 , mReNegativeZero(
"^\\-0(?:[.,]0*)?$" )
205 return !( *
this == other );
215 while ( precision < 0 )
232 QString valueStr = QLocale().toString( value,
'f',
mPrecision );
236 valueStr = valueStr.mid( 1 );
241 QString valueStr = QLocale().toString( value *
mNumberScale,
'f', 0 );
242 if ( valueStr == QLatin1String(
"-0" ) )
244 if ( valueStr != QLatin1String(
"0" ) )
256 return legend.replace( QLatin1String(
"%1" ), lowerStr ).replace( QLatin1String(
"%2" ), upperStr );
261 mFormat = element.attribute( QStringLiteral(
"format" ),
262 element.attribute( QStringLiteral(
"prefix" ), QStringLiteral(
" " ) ) +
"%1" +
263 element.attribute( QStringLiteral(
"separator" ), QStringLiteral(
" - " ) ) +
"%2" +
264 element.attribute( QStringLiteral(
"suffix" ), QStringLiteral(
" " ) )
266 setPrecision( element.attribute( QStringLiteral(
"decimalplaces" ), QStringLiteral(
"4" ) ).toInt() );
267 mTrimTrailingZeroes = element.attribute( QStringLiteral(
"trimtrailingzeroes" ), QStringLiteral(
"false" ) ) == QLatin1String(
"true" );
272 element.setAttribute( QStringLiteral(
"format" ),
mFormat );
273 element.setAttribute( QStringLiteral(
"decimalplaces" ),
mPrecision );
274 element.setAttribute( QStringLiteral(
"trimtrailingzeroes" ),
mTrimTrailingZeroes ? QStringLiteral(
"true" ) : QStringLiteral(
"false" ) );
281 , mAttrName( attrName )
288 const auto constRanges =
ranges;
302 const auto constMRanges =
mRanges;
305 if ( range.lowerValue() <= value && range.upperValue() >= value )
308 return range.symbol();
320 const auto constMRanges =
mRanges;
323 if ( range.lowerValue() <= value && range.upperValue() >= value )
326 return QString::number( i );
345 if ( mAttrNum < 0 || mAttrNum >= attrs.count() )
359 QVariant value = valueForFeature( feature, context );
362 if ( value.isNull() )
384 const auto constMRanges =
mRanges;
387 if ( !range.symbol() )
390 range.symbol()->startRender( context, fields );
398 const auto constMRanges =
mRanges;
401 if ( !range.symbol() )
404 range.symbol()->stopRender( context );
410 QSet<QString> attributes;
422 QgsRangeList::const_iterator range_it =
mRanges.constBegin();
423 for ( ; range_it !=
mRanges.constEnd(); ++range_it )
449 if ( rangeIndex < 0 || rangeIndex >=
mRanges.size() )
451 mRanges[rangeIndex].setSymbol( symbol );
457 if ( rangeIndex < 0 || rangeIndex >=
mRanges.size() )
459 mRanges[rangeIndex].setLabel( label );
465 if ( rangeIndex < 0 || rangeIndex >=
mRanges.size() )
476 if ( rangeIndex < 0 || rangeIndex >=
mRanges.size() )
487 if ( rangeIndex < 0 || rangeIndex >=
mRanges.size() )
489 mRanges[rangeIndex].setRenderState( value );
495 QString s = QStringLiteral(
"GRADUATED: attr %1\n" ).arg(
mAttrName );
496 for (
int i = 0; i <
mRanges.count(); i++ )
527 newProps[ QStringLiteral(
"attribute" )] =
mAttrName;
532 for ( QgsRangeList::const_iterator it =
mRanges.constBegin(); it !=
mRanges.constEnd(); ++it )
534 it->toSld( doc, element, newProps, first );
543 lst.reserve(
mRanges.count() );
544 const auto constMRanges =
mRanges;
547 lst.append( range.symbol() );
559 if ( breaks.size() > 1 )
561 std::sort( breaks.begin(), breaks.end() );
563 double distBelowSymmetricValue = std::fabs( breaks[0] - symmetryPoint );
564 double distAboveSymmetricValue = std::fabs( breaks[ breaks.size() - 2 ] -
symmetryPoint ) ;
565 double absMin = std::min( distAboveSymmetricValue, distBelowSymmetricValue );
568 for (
int i = 0; i <= breaks.size() - 2; ++i )
571 if ( std::fabs( breaks.at( i ) -
symmetryPoint ) >= ( absMin - std::fabs( breaks[0] - breaks[1] ) / 100. ) )
573 breaks.removeAt( i );
580 breaks.removeAt( breaks.indexOf( symmetryPoint ) );
589 QList<double> breaks;
590 if ( !useSymmetricMode )
592 double step = ( maximum - minimum ) / classes;
594 double value = minimum;
595 breaks.reserve( classes );
596 for (
int i = 0; i < classes; i++ )
599 breaks.append( value );
603 breaks[classes - 1] = maximum;
605 else if ( useSymmetricMode )
607 double distBelowSymmetricValue = std::abs( minimum - symmetryPoint );
608 double distAboveSymmetricValue = std::abs( maximum - symmetryPoint ) ;
612 if ( classes % 2 == 0 )
617 if ( classes % 2 == 1 )
620 double step = 2 * std::min( distBelowSymmetricValue, distAboveSymmetricValue ) / classes;
622 breaks.reserve( classes );
623 double value = ( distBelowSymmetricValue < distAboveSymmetricValue ) ? minimum : maximum - classes * step;
625 for (
int i = 0; i < classes; i++ )
628 breaks.append( value );
630 breaks[classes - 1] = maximum;
635 static QList<double> _calcQuantileBreaks( QList<double> values,
int classes )
646 std::sort( values.begin(), values.end() );
648 QList<double> breaks;
651 if ( values.isEmpty() )
654 int n = values.count();
655 double Xq = n > 0 ? values[0] : 0.0;
657 breaks.reserve( classes );
658 for (
int i = 1; i < classes; i++ )
662 double q = i /
static_cast< double >( classes );
663 double a = q * ( n - 1 );
664 int aa =
static_cast< int >( a );
667 Xq = ( 1 - r ) * values[aa] + r * values[aa + 1];
672 breaks.append( values[ n - 1 ] );
688 if ( values.isEmpty() )
689 return QList<double>();
693 int n = values.count();
694 double minimum = values[0];
695 double maximum = values[0];
697 for (
int i = 0; i < n; i++ )
700 minimum = std::min( values[i], minimum );
701 maximum = std::max( values[i], maximum );
703 mean = mean /
static_cast< double >( n );
706 for (
int i = 0; i < n; i++ )
708 sd = values[i] - mean;
711 stdDev = std::sqrt( stdDev / n );
719 for (
int i = 0; i < breaks.count(); i++ )
721 labels.append( breaks[i] );
727 static QList<double> _calcJenksBreaks( QList<double> values,
int classes,
728 double minimum,
double maximum,
729 int maximumSize = 3000 )
741 if ( values.isEmpty() )
742 return QList<double>();
746 return QList<double>() << maximum;
749 if ( classes >= values.size() )
754 QVector<double> sample;
757 if ( values.size() > maximumSize )
763 sample.resize( std::max( maximumSize, values.size() / 10 ) );
765 QgsDebugMsg( QStringLiteral(
"natural breaks (jenks) sample size: %1" ).arg( sample.size() ) );
766 QgsDebugMsg( QStringLiteral(
"values:%1" ).arg( values.size() ) );
768 sample[ 0 ] = minimum;
769 sample[ 1 ] = maximum;
770 for (
int i = 2; i < sample.size(); i++ )
774 int j = std::floor( r / RAND_MAX * ( values.size() - 1 ) );
775 sample[ i ] = values[ j ];
780 sample = values.toVector();
783 int n = sample.size();
786 std::sort( sample.begin(), sample.end() );
788 QVector< QVector<int> > matrixOne( n + 1 );
789 QVector< QVector<double> > matrixTwo( n + 1 );
791 for (
int i = 0; i <= n; i++ )
793 matrixOne[i].resize( classes + 1 );
794 matrixTwo[i].resize( classes + 1 );
797 for (
int i = 1; i <= classes; i++ )
801 matrixTwo[0][i] = 0.0;
802 for (
int j = 2; j <= n; j++ )
804 matrixTwo[j][i] = std::numeric_limits<double>::max();
808 for (
int l = 2; l <= n; l++ )
816 for (
int m = 1; m <= l; m++ )
820 double val = sample[ i3 - 1 ];
826 v = s2 - ( s1 * s1 ) / static_cast< double >( w );
830 for (
int j = 2; j <= classes; j++ )
832 if ( matrixTwo[l][j] >= v + matrixTwo[i4][j - 1] )
834 matrixOne[l][j] = i4;
835 matrixTwo[l][j] = v + matrixTwo[i4][j - 1];
844 QVector<double> breaks( classes );
845 breaks[classes - 1] = sample[n - 1];
847 for (
int j = classes, k = n; j >= 2; j-- )
849 int id = matrixOne[k][j] - 1;
850 breaks[j - 2] = sample[id];
851 k = matrixOne[k][j] - 1;
854 return breaks.toList();
857 static QStringList _breaksAsStrings(
const QList<double> &breaks )
859 QStringList breaksAsStrings;
860 for (
int i = 0; i < breaks.count() - 1; i++ )
862 breaksAsStrings << QString::number( breaks.at( i ),
'f', 2 );
864 return breaksAsStrings;
869 const QString &attrName,
891 r->
updateClasses( vlayer, mode, classes, useSymmetricMode, symmetryPoint, astride );
912 QList<double> values;
913 bool valuesLoaded =
false;
923 if ( !ok || values.isEmpty() )
926 auto result = std::minmax_element( values.begin(), values.end() );
927 minimum = *result.first;
928 maximum = *result.second;
937 QgsDebugMsg( QStringLiteral(
"min %1 // max %2" ).arg( minimum ).arg( maximum ) );
938 QList<double> breaks;
939 QList<double> labels;
954 if ( useSymmetricMode )
970 breaks = _calcQuantileBreaks( values, nclasses );
971 else if ( mode ==
Jenks )
972 breaks = _calcJenksBreaks( values, nclasses, minimum, maximum );
973 else if ( mode ==
StdDev )
974 breaks = _calcStdDevBreaks( values, nclasses, labels,
mUseSymmetricMode, symmetryPoint, astride );
983 double lower, upper = minimum;
989 for ( QList<double>::iterator it = breaks.begin(); it != breaks.end(); ++it, ++i )
999 label =
"< " + QString::number( labels[i],
'f', 2 ) +
" Std Dev";
1001 else if ( i == labels.count() - 1 )
1003 label =
">= " + QString::number( labels[i - 1],
'f', 2 ) +
" Std Dev";
1007 label = QString::number( labels[i - 1],
'f', 2 ) +
" Std Dev" +
" - " + QString::number( labels[i],
'f', 2 ) +
" Std Dev";
1023 QDomElement symbolsElem = element.firstChildElement( QStringLiteral(
"symbols" ) );
1024 if ( symbolsElem.isNull() )
1027 QDomElement rangesElem = element.firstChildElement( QStringLiteral(
"ranges" ) );
1028 if ( rangesElem.isNull() )
1034 QDomElement rangeElem = rangesElem.firstChildElement();
1035 while ( !rangeElem.isNull() )
1037 if ( rangeElem.tagName() == QLatin1String(
"range" ) )
1039 double lowerValue = rangeElem.attribute( QStringLiteral(
"lower" ) ).toDouble();
1040 double upperValue = rangeElem.attribute( QStringLiteral(
"upper" ) ).toDouble();
1041 QString symbolName = rangeElem.attribute( QStringLiteral(
"symbol" ) );
1042 QString label = rangeElem.attribute( QStringLiteral(
"label" ) );
1043 bool render = rangeElem.attribute( QStringLiteral(
"render" ), QStringLiteral(
"true" ) ) != QLatin1String(
"false" );
1044 if ( symbolMap.contains( symbolName ) )
1046 QgsSymbol *symbol = symbolMap.take( symbolName );
1047 ranges.append(
QgsRendererRange( lowerValue, upperValue, symbol, label, render ) );
1050 rangeElem = rangeElem.nextSiblingElement();
1053 QString attrName = element.attribute( QStringLiteral(
"attr" ) );
1057 QString attrMethod = element.attribute( QStringLiteral(
"graduatedMethod" ) );
1058 if ( !attrMethod.isEmpty() )
1071 QDomElement sourceSymbolElem = element.firstChildElement( QStringLiteral(
"source-symbol" ) );
1072 if ( !sourceSymbolElem.isNull() )
1075 if ( sourceSymbolMap.contains( QStringLiteral(
"0" ) ) )
1083 QDomElement sourceColorRampElem = element.firstChildElement( QStringLiteral(
"colorramp" ) );
1084 if ( !sourceColorRampElem.isNull() && sourceColorRampElem.attribute( QStringLiteral(
"name" ) ) == QLatin1String(
"[source]" ) )
1090 QDomElement modeElem = element.firstChildElement( QStringLiteral(
"mode" ) );
1091 if ( !modeElem.isNull() )
1093 QString modeString = modeElem.attribute( QStringLiteral(
"name" ) );
1094 if ( modeString == QLatin1String(
"equal" ) )
1096 else if ( modeString == QLatin1String(
"quantile" ) )
1098 else if ( modeString == QLatin1String(
"jenks" ) )
1100 else if ( modeString == QLatin1String(
"stddev" ) )
1102 else if ( modeString == QLatin1String(
"pretty" ) )
1107 QDomElement symmetricModeElem = element.firstChildElement( QStringLiteral(
"symmetricMode" ) );
1108 if ( !symmetricModeElem.isNull() )
1110 QString symmetricEnabled = symmetricModeElem.attribute( QStringLiteral(
"enabled" ) );
1113 QString symmetricPointString = symmetricModeElem.attribute( QStringLiteral(
"symmetryPoint" ) );
1115 QString breaksForPretty = symmetricModeElem.attribute( QStringLiteral(
"valueForCboPrettyBreaks" ) );
1118 QString astrideEnabled = symmetricModeElem.attribute( QStringLiteral(
"astride" ) );
1121 QDomElement rotationElem = element.firstChildElement( QStringLiteral(
"rotation" ) );
1122 if ( !rotationElem.isNull() && !rotationElem.attribute( QStringLiteral(
"field" ) ).isEmpty() )
1133 QDomElement sizeScaleElem = element.firstChildElement( QStringLiteral(
"sizescale" ) );
1134 if ( !sizeScaleElem.isNull() && !sizeScaleElem.attribute( QStringLiteral(
"field" ) ).isEmpty() )
1140 sizeScaleElem.attribute( QStringLiteral(
"field" ) ) );
1146 sizeScaleElem.attribute( QStringLiteral(
"field" ) ) );
1150 QDomElement labelFormatElem = element.firstChildElement( QStringLiteral(
"labelformat" ) );
1151 if ( ! labelFormatElem.isNull() )
1158 QDomElement ddsLegendSizeElem = element.firstChildElement( QStringLiteral(
"data-defined-size-legend" ) );
1159 if ( !ddsLegendSizeElem.isNull() )
1170 rendererElem.setAttribute( QStringLiteral(
"type" ), QStringLiteral(
"graduatedSymbol" ) );
1171 rendererElem.setAttribute( QStringLiteral(
"symbollevels" ), (
mUsingSymbolLevels ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) ) );
1172 rendererElem.setAttribute( QStringLiteral(
"forceraster" ), (
mForceRaster ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) ) );
1173 rendererElem.setAttribute( QStringLiteral(
"attr" ),
mAttrName );
1179 QDomElement rangesElem = doc.createElement( QStringLiteral(
"ranges" ) );
1180 QgsRangeList::const_iterator it =
mRanges.constBegin();
1181 for ( ; it !=
mRanges.constEnd(); ++it )
1184 QString symbolName = QString::number( i );
1185 symbols.insert( symbolName, range.
symbol() );
1187 QDomElement rangeElem = doc.createElement( QStringLiteral(
"range" ) );
1188 rangeElem.setAttribute( QStringLiteral(
"lower" ), QString::number( range.
lowerValue(),
'f', 15 ) );
1189 rangeElem.setAttribute( QStringLiteral(
"upper" ), QString::number( range.
upperValue(),
'f', 15 ) );
1190 rangeElem.setAttribute( QStringLiteral(
"symbol" ), symbolName );
1191 rangeElem.setAttribute( QStringLiteral(
"label" ), range.
label() );
1192 rangeElem.setAttribute( QStringLiteral(
"render" ), range.
renderState() ? QStringLiteral(
"true" ) : QStringLiteral(
"false" ) );
1193 rangesElem.appendChild( rangeElem );
1197 rendererElem.appendChild( rangesElem );
1201 rendererElem.appendChild( symbolsElem );
1207 sourceSymbols.insert( QStringLiteral(
"0" ),
mSourceSymbol.get() );
1209 rendererElem.appendChild( sourceSymbolElem );
1216 rendererElem.appendChild( colorRampElem );
1224 modeString = QStringLiteral(
"equal" );
1227 modeString = QStringLiteral(
"quantile" );
1230 modeString = QStringLiteral(
"jenks" );
1233 modeString = QStringLiteral(
"stddev" );
1236 modeString = QStringLiteral(
"pretty" );
1241 if ( !modeString.isEmpty() )
1243 QDomElement modeElem = doc.createElement( QStringLiteral(
"mode" ) );
1244 modeElem.setAttribute( QStringLiteral(
"name" ), modeString );
1245 rendererElem.appendChild( modeElem );
1249 QDomElement symmetricModeElem = doc.createElement( QStringLiteral(
"symmetricMode" ) );
1250 symmetricModeElem.setAttribute( QStringLiteral(
"enabled" ),
mUseSymmetricMode ? QStringLiteral(
"true" ) : QStringLiteral(
"false" ) );
1251 symmetricModeElem.setAttribute( QStringLiteral(
"symmetryPoint" ),
mSymmetryPoint );
1252 symmetricModeElem.setAttribute( QStringLiteral(
"astride" ),
mAstride ? QStringLiteral(
"true" ) : QStringLiteral(
"false" ) );
1259 breaks.append(
'/' );
1263 symmetricModeElem.setAttribute( QStringLiteral(
"valueForCboPrettyBreaks" ), breaks );
1266 rendererElem.appendChild( symmetricModeElem );
1268 QDomElement rotationElem = doc.createElement( QStringLiteral(
"rotation" ) );
1269 rendererElem.appendChild( rotationElem );
1271 QDomElement sizeScaleElem = doc.createElement( QStringLiteral(
"sizescale" ) );
1272 rendererElem.appendChild( sizeScaleElem );
1274 QDomElement labelFormatElem = doc.createElement( QStringLiteral(
"labelformat" ) );
1276 rendererElem.appendChild( labelFormatElem );
1283 QDomElement
orderBy = doc.createElement( QStringLiteral(
"orderby" ) );
1285 rendererElem.appendChild( orderBy );
1287 rendererElem.setAttribute( QStringLiteral(
"enableorderby" ), (
mOrderByEnabled ? QStringLiteral(
"1" ) : QStringLiteral(
"0" ) ) );
1291 QDomElement ddsLegendElem = doc.createElement( QStringLiteral(
"data-defined-size-legend" ) );
1293 rendererElem.appendChild( ddsLegendElem );
1296 return rendererElem;
1303 const auto constMRanges =
mRanges;
1306 lst <<
QgsLegendSymbolItem( range.symbol(), range.label(), QString::number( i++ ), true );
1317 const auto constMRanges =
mRanges;
1324 if ( sSize && sSize != ddSize )
1327 return baseLegendSymbolItems();
1344 lst += baseLegendSymbolItems();
1349 return baseLegendSymbolItems();
1354 QVariant value = valueForFeature( feature, context );
1357 if ( value.isNull() )
1358 return QSet< QString >();
1362 if ( !key.isNull() )
1363 return QSet< QString >() << key;
1365 return QSet< QString >();
1392 double min = std::numeric_limits<double>::max();
1393 for (
int i = 0; i <
mRanges.count(); i++ )
1397 sz = static_cast< QgsMarkerSymbol * >(
mRanges[i].symbol() )->size();
1399 sz = static_cast< QgsLineSymbol * >(
mRanges[i].symbol() )->width();
1400 min = std::min( sz, min );
1407 double max = std::numeric_limits<double>::min();
1408 for (
int i = 0; i <
mRanges.count(); i++ )
1412 sz = static_cast< QgsMarkerSymbol * >(
mRanges[i].symbol() )->size();
1414 sz = static_cast< QgsLineSymbol * >(
mRanges[i].symbol() )->width();
1415 max = std::max( sz, max );
1422 for (
int i = 0; i <
mRanges.count(); i++ )
1424 std::unique_ptr<QgsSymbol> symbol(
mRanges.at( i ).symbol() ?
mRanges.at( i ).symbol()->clone() : nullptr );
1425 const double size =
mRanges.count() > 1
1426 ? minSize + i * ( maxSize - minSize ) / (
mRanges.count() - 1 )
1427 : .5 * ( maxSize + minSize );
1429 static_cast< QgsMarkerSymbol * >( symbol.get() )->setSize( size );
1431 static_cast< QgsLineSymbol * >( symbol.get() )->setWidth( size );
1446 const auto constMRanges =
mRanges;
1449 QgsSymbol *symbol = range.symbol() ? range.symbol()->
clone() :
nullptr;
1453 colorValue = (
mRanges.count() > 1 ?
static_cast< double >( i ) / (
mRanges.count() - 1 ) : 0 );
1469 const auto constMRanges =
mRanges;
1472 std::unique_ptr<QgsSymbol> symbol( sym->
clone() );
1475 symbol->setColor( range.symbol()->color() );
1480 static_cast<QgsMarkerSymbol *>( symbol.get() )->setSize(
1481 static_cast<QgsMarkerSymbol *>( range.symbol() )->size() );
1483 static_cast<QgsLineSymbol *>( symbol.get() )->setWidth(
1484 static_cast<QgsLineSymbol *>( range.symbol() )->width() );
1500 int index = key.toInt( &ok );
1501 if ( ok && index >= 0 && index <
mRanges.size() )
1502 return mRanges.at( index ).renderState();
1510 int index = key.toInt( &ok );
1518 int index = key.toInt( &ok );
1528 QString label = QStringLiteral(
"0.0 - 0.0" );
1541 QMutableListIterator< QgsRendererRange > it(
mRanges );
1542 while ( it.hasNext() )
1557 it.setValue( range );
1559 it.insert( newRange );
1564 if ( updateSymbols )
1597 for ( QgsRangeList::iterator it =
mRanges.begin(); it !=
mRanges.end(); ++it )
1609 double minClassRange = 0.0;
1610 const auto constMRanges =
mRanges;
1613 double range = rendererRange.upperValue() - rendererRange.lowerValue();
1616 if ( minClassRange == 0.0 || range < minClassRange )
1617 minClassRange = range;
1619 if ( minClassRange <= 0.0 )
1626 double nextDpMinRange = 0.0000000099;
1627 while ( ndp > 0 && nextDpMinRange < minClassRange )
1630 nextDpMinRange *= 10.0;
1638 if ( from < 0 || from >=
mRanges.size() || to < 0 || to >=
mRanges.size() )
1655 if ( order == Qt::AscendingOrder )
1668 std::sort( sortedRanges.begin(), sortedRanges.end(),
valueLessThan );
1670 QgsRangeList::const_iterator it = sortedRanges.constBegin();
1671 if ( it == sortedRanges.constEnd() )
1674 if ( ( *it ).upperValue() < ( *it ).lowerValue() )
1677 double prevMax = ( *it ).upperValue();
1680 for ( ; it != sortedRanges.constEnd(); ++it )
1682 if ( ( *it ).upperValue() < ( *it ).lowerValue() )
1685 if ( ( *it ).lowerValue() < prevMax )
1688 prevMax = ( *it ).upperValue();
1696 std::sort( sortedRanges.begin(), sortedRanges.end(),
valueLessThan );
1698 QgsRangeList::const_iterator it = sortedRanges.constBegin();
1699 if ( it == sortedRanges.constEnd() )
1702 double prevMax = ( *it ).upperValue();
1705 for ( ; it != sortedRanges.constEnd(); ++it )
1710 prevMax = ( *it ).upperValue();
1717 return QString::localeAwareCompare( r1.
label(), r2.
label() ) < 0;
1727 if ( order == Qt::AscendingOrder )
1740 if ( renderer->
type() == QLatin1String(
"graduatedSymbol" ) )
1744 else if ( renderer->
type() == QLatin1String(
"pointDisplacement" ) || renderer->
type() == QLatin1String(
"pointCluster" ) )
1747 if ( pointDistanceRenderer )
1750 else if ( renderer->
type() == QLatin1String(
"invertedPolygonRenderer" ) )
1753 if ( invertedPolygonRenderer )
1765 if ( !symbols.isEmpty() )
1792 return "GraduatedColor";
1794 return "GraduatedSize";
An abstract base class for distance based point renderers (e.g., clusterer and displacement renderers...
int lookupField(const QString &fieldName) const
Looks up field's index from the field name.
Class for parsing and evaluation of expressions (formerly called "search strings").
const QgsRendererRangeLabelFormat & labelFormat() const
Returns the label format used to generate default classification labels.
bool hasParserError() const
Returns true if an error occurred when parsing the input expression.
static QgsGraduatedSymbolRenderer * convertFromRenderer(const QgsFeatureRenderer *renderer)
creates a QgsGraduatedSymbolRenderer from an existing renderer.
The class is used as a container of context for various read/write operations on other objects...
void stopRender(QgsRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
double rendererScale() const
Returns the renderer map scale.
static QgsSymbol::ScaleMethod decodeScaleMethod(const QString &str)
std::unique_ptr< QgsSymbol > mSourceSymbol
QList< QgsLegendSymbolItem > QgsLegendSymbolList
bool filterNeedsGeometry() const override
Returns true if this renderer requires the geometry to apply the filter.
QgsFeatureRequest::OrderBy mOrderBy
static bool createFunctionElement(QDomDocument &doc, QDomElement &element, const QString &function)
bool labelLessThan(const QgsRendererRange &r1, const QgsRendererRange &r2)
static QgsFeatureRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
create renderer from XML element
Abstract base class for all rendered symbols.
bool updateRangeUpperValue(int rangeIndex, double value)
QList< QgsRendererRange > QgsRangeList
bool rangesOverlap() const
Tests whether classes assigned to the renderer have ranges which overlap.
void setLabel(const QString &label)
virtual QgsColorRamp * clone() const =0
Creates a clone of the color ramp.
void setSymmetryPoint(double symmetryPoint)
Set the pivot point.
static QList< double > getDoubleValues(const QgsVectorLayer *layer, const QString &fieldOrExpression, bool &ok, bool selectedOnly=false, int *nullCount=nullptr, QgsFeedback *feedback=nullptr)
Fetches all double values from a specified field name or expression.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
QgsFeatureRequest::OrderBy orderBy() const
Gets the order in which features shall be processed by this renderer.
Abstract base class for color ramps.
static bool isDefaultStack(QgsPaintEffect *effect)
Tests whether a paint effect matches the default effects stack.
QStringList mListForCboPrettyBreaks
void addBreak(double breakValue, bool updateSymbols=true)
Add a breakpoint by splitting existing classes so that the specified value becomes a break between tw...
static QDomElement saveColorRamp(const QString &name, QgsColorRamp *ramp, QDomDocument &doc)
Encodes a color ramp's settings to an XML element.
void setGraduatedMethod(GraduatedMethod method)
set the method used for graduation (either size or color)
void updateClasses(QgsVectorLayer *vlayer, Mode mode, int nclasses, bool useSymmetricMode=false, double symmetryPoint=0.0, bool astride=false)
Recalculate classes for a layer.
void startRender(QgsRenderContext &context, const QgsFields &fields) override
Must be called when a new render cycle is started.
QgsWkbTypes::GeometryType geometryType() const
Returns point, line or polygon.
Container of fields for a vector layer.
void setRenderState(bool render)
#define RENDERER_TAG_NAME
void setUsingSymbolLevels(bool usingSymbolLevels)
bool needsGeometry() const
Returns true if the expression uses feature geometry for some computation.
static void clearSymbolMap(QgsSymbolMap &symbols)
QgsRendererRange & operator=(QgsRendererRange range)
void setAstride(bool astride)
Set if we want a central class astride the pivot value.
QgsPaintEffect * mPaintEffect
QSet< QString > referencedColumns() const
Gets list of columns referenced by the expression.
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
void setSymbolSizes(double minSize, double maxSize)
set varying symbol size for classes
bool operator<(const QgsRendererRange &other) const
QgsLegendSymbolList legendSymbolList() const
Generates legend symbol items according to the configuration.
static const char * graduatedMethodStr(GraduatedMethod method)
std::unique_ptr< QgsExpression > mExpression
void setUpperValue(double upperValue)
void addClass(QgsSymbol *symbol)
QMap< QString, QString > QgsStringMap
QgsSymbol * symbolForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
To be overridden.
A marker symbol type, for rendering Point and MultiPoint geometries.
void setLegendSymbolItem(const QString &key, QgsSymbol *symbol) override
Sets the symbol to be used for a legend symbol item.
bool rangesHaveGaps() const
Tests whether classes assigned to the renderer have gaps between the ranges.
void checkLegendSymbolItem(const QString &key, bool state=true) override
item in symbology was checked
void sortByValue(Qt::SortOrder order=Qt::AscendingOrder)
void setUseSymmetricMode(bool useSymmetricMode)
Set if we want to classify symmetric around a given value.
double lowerValue() const
QSet< QString > legendKeysForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns legend keys matching a specified feature.
bool updateRangeSymbol(int rangeIndex, QgsSymbol *symbol)
GraduatedMethod mGraduatedMethod
QList< QgsSymbol * > QgsSymbolList
static QgsSymbol * defaultSymbol(QgsWkbTypes::GeometryType geomType)
Returns a new default symbol for the specified geometry type.
void updateColorRamp(QgsColorRamp *ramp=nullptr)
Update the color ramp used.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
void setListForCboPrettyBreaks(const QStringList &listForCboPrettyBreaks)
Set the list of breaks used in the prettybreaks mode, which is needed to recover this list in saved c...
QgsInvertedPolygonRenderer is a polygon-only feature renderer used to display features inverted...
bool updateRangeLowerValue(int rangeIndex, double value)
static QDomElement saveSymbols(QgsSymbolMap &symbols, const QString &tagName, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a collection of symbols to XML with specified tagName for the top-level element.
void setLowerValue(double lowerValue)
bool labelGreaterThan(const QgsRendererRange &r1, const QgsRendererRange &r2)
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsColorRamp * sourceColorRamp()
Returns the source color ramp, from which each classes' color is derived.
bool astride() const
Returns if we want to have a central class astride the pivot value.
void updateFromSymbolAndProperty(const QgsMarkerSymbol *symbol, const QgsProperty &ddSize)
Updates the list of classes, source symbol and title label from given symbol and property.
static QgsColorRamp * loadColorRamp(QDomElement &element)
Creates a color ramp from the settings encoded in an XML element.
static void convertSymbolSizeScale(QgsSymbol *symbol, QgsSymbol::ScaleMethod method, const QString &field)
static QList< QgsExpressionContextScope * > globalProjectLayerScopes(const QgsMapLayer *layer)
Creates a list of three scopes: global, layer's project and layer.
QgsSymbol * symbol() const
QVariant minimumValue(int index) const FINAL
Returns the minimum value for an attribute column or an invalid variant in case of error...
static QgsGraduatedSymbolRenderer * createRenderer(QgsVectorLayer *vlayer, const QString &attrName, int classes, Mode mode, QgsSymbol *symbol, QgsColorRamp *ramp, const QgsRendererRangeLabelFormat &legendFormat=QgsRendererRangeLabelFormat(), bool useSymmetricMode=false, double symmetryPoint=0.0, QStringList listForCboPrettyBreaks=QStringList(), bool astride=false)
Creates a new graduated renderer.
A store for object properties.
double symmetryPoint() const
Returns the pivot value for symmetric classification.
bool valueLessThan(const QgsRendererRange &r1, const QgsRendererRange &r2)
~QgsGraduatedSymbolRenderer() override
static QgsSymbolMap loadSymbols(QDomElement &element, const QgsReadWriteContext &context)
Reads a collection of symbols from XML and returns them in a map. Caller is responsible for deleting ...
void swap(QgsRendererRange &other)
bool orderByEnabled() const
Returns whether custom ordering will be applied before features are processed by this renderer...
QgsDataDefinedSizeLegend * dataDefinedSizeLegend() const
Returns configuration of appearance of legend when using data-defined size for marker symbols...
QSet< QString > usedAttributes(const QgsRenderContext &context) const override
Returns a list of attributes required by this renderer.
void setOrderBy(const QgsFeatureRequest::OrderBy &orderBy)
Define the order in which features shall be processed by this renderer.
void moveClass(int from, int to)
Moves the category at index position from to index position to.
QgsSymbol * originalSymbolForFeature(const QgsFeature &feature, QgsRenderContext &context) const override
Returns symbol for feature.
QgsExpressionContext & expressionContext()
Gets the expression context.
QgsProperty dataDefinedSize() const
Returns data defined size for whole symbol (including all symbol layers).
QgsRendererRange()=default
Constructor for QgsRendererRange.
void calculateLabelPrecision(bool updateRanges=true)
Reset the label decimal places to a numberbased on the minimum class interval.
static QList< double > prettyBreaks(double minimum, double maximum, int classes)
Computes a sequence of about 'classes' equally spaced round values which cover the range of values fr...
static void convertSymbolRotation(QgsSymbol *symbol, const QString &field)
bool legendSymbolItemsCheckable() const override
items of symbology items in legend should be checkable
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
double minSymbolSize() const
Returns the min symbol size when graduated by size.
QSet< QString > usedAttributes(const QgsRenderContext &context) const
Returns a list of attributes required to render this feature.
The class stores information about one class/rule of a vector layer renderer in a unified way that ca...
Contains information about the context of a rendering operation.
QgsRendererRangeLabelFormat mLabelFormat
bool usingSymbolLevels() const
QgsSymbolList symbols(QgsRenderContext &context) const override
Returns list of symbols used by the renderer.
QgsLegendSymbolList legendSymbolItems() const override
Returns a list of symbology items for the legend.
void sortByLabel(Qt::SortOrder order=Qt::AscendingOrder)
void setSymbol(QgsSymbol *s)
GraduatedMethod graduatedMethod() const
Returns the method used for graduation (either size or color)
QgsGraduatedSymbolRenderer(const QString &attrName=QString(), const QgsRangeList &ranges=QgsRangeList())
virtual void startRender(QgsRenderContext &context, const QgsFields &fields)
Must be called when a new render cycle is started.
double maxSymbolSize() const
Returns the max symbol size when graduated by size.
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
virtual QgsSymbol * clone() const =0
Returns a deep copy of this symbol.
bool useSymmetricMode() const
Returns if we want to classify symmetric around a given value.
void setDataDefinedSizeLegend(QgsDataDefinedSizeLegend *settings)
Configures appearance of legend when renderer is configured to use data-defined size for marker symbo...
void CORE_EXPORT save(QDomElement &elem) const
Serialize to XML.
QString dump() const override
Returns debug information about this renderer.
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props, bool firstRange=false) const
Creates a DOM element representing the range in SLD format.
void toSld(QDomDocument &doc, QDomElement &element, const QgsStringMap &props=QgsStringMap()) const override
used from subclasses to create SLD Rule elements following SLD v1.1 specs
QgsGraduatedSymbolRenderer * clone() const override
Create a deep copy of this renderer.
double upperValue() const
virtual void stopRender(QgsRenderContext &context)
Must be called when a render cycle has finished, to allow the renderer to clean up.
QMap< QString, QgsSymbol *> QgsSymbolMap
std::unique_ptr< QgsSymbol > mSymbol
void copyRendererData(QgsFeatureRenderer *destRenderer) const
Clones generic renderer data to another renderer.
static QList< double > calcEqualIntervalBreaks(double minimum, double maximum, int classes, bool useSymmetricMode, double symmetryPoint, bool astride)
Compute the equal interval classification.
bool updateRangeRenderState(int rangeIndex, bool render)
bool valueGreaterThan(const QgsRendererRange &r1, const QgsRendererRange &r2)
bool updateRangeLabel(int rangeIndex, const QString &label)
bool legendSymbolItemChecked(const QString &key) override
items of symbology items in legend is checked
void appendScopes(const QList< QgsExpressionContextScope *> &scopes)
Appends a list of scopes to the end of the context.
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) override
store renderer info to XML element
static void makeBreaksSymmetric(QList< double > &breaks, double symmetryPoint, bool astride)
Remove the breaks that are above the existing opposite sign classes to keep colors symmetrically bala...
int mAttrNum
attribute index (derived from attribute name in startRender)
int ANALYSIS_EXPORT lower(int n, int i)
Lower function.
std::unique_ptr< QgsColorRamp > mSourceColorRamp
const QgsFeatureRenderer * embeddedRenderer() const override
Returns the current embedded renderer (subrenderer) for this feature renderer.
QString legendKeyForValue(double value) const
Returns the matching legend key for a value.
QVariant maximumValue(int index) const FINAL
Returns the maximum value for an attribute column or an invalid variant in case of error...
Represents a vector layer which manages a vector based data sets.
Object that keeps configuration of appearance of marker symbol's data-defined size in legend...
QgsSymbol * symbolForValue(double value) const
Gets the symbol which is used to represent value.
std::unique_ptr< QgsDataDefinedSizeLegend > mDataDefinedSizeLegend
const QgsRangeList & ranges() const
static QgsDataDefinedSizeLegend * readXml(const QDomElement &elem, const QgsReadWriteContext &context) SIP_FACTORY
Creates instance from given element and returns it (caller takes ownership). Returns nullptr on error...
void setSourceColorRamp(QgsColorRamp *ramp)
Sets the source color ramp.
void updateSymbols(QgsSymbol *sym)
Update all the symbols but leave breaks and colors.
void setOrderByEnabled(bool enabled)
Sets whether custom ordering should be applied before features are processed by this renderer...
QgsSymbol * sourceSymbol()
Returns the renderer's source symbol, which is the base symbol used for the each classes' symbol befo...
void setSourceSymbol(QgsSymbol *sym)
Sets the source symbol for the renderer, which is the base symbol used for the each classes' symbol b...
virtual QgsFeatureRenderer * clone() const =0
Create a deep copy of this renderer.
void deleteClass(int idx)
bool isActive() const
Returns whether the property is currently active.
void setLabelFormat(const QgsRendererRangeLabelFormat &labelFormat, bool updateRanges=false)
Set the label format used to generate default classification labels.
void setColor(const QColor &color)
Sets the color for the symbol.
QStringList listForCboPrettyBreaks() const
Returns the list of breaks used in the prettybreaks mode.
virtual bool saveProperties(QDomDocument &doc, QDomElement &element) const
Saves the current state of the effect to a DOM element.