16 #include <QRegularExpression> 
   34   values.reserve( 
classes.count() );
 
   35   for ( 
int i = 0 ; i < 
classes.count(); i++ )
 
   36     values << 
classes.at( i ).upperBound();
 
   41   : mFlags( properties )
 
   42   , mCodeComplexity( codeComplexity )
 
   43   , mLabelFormat( QStringLiteral( 
"%1 - %2" ) )
 
   49   qDeleteAll( mParameters );
 
   54   c->setSymmetricMode( mSymmetricEnabled, mSymmetryPoint, mSymmetryAstride );
 
   55   c->setLabelFormat( mLabelFormat );
 
   56   c->setLabelPrecision( mLabelPrecision );
 
   57   c->setLabelTrimTrailingZeroes( mLabelTrimTrailingZeroes );
 
   58   c->setParameterValues( mParameterValues );
 
   63   const QString methodId = element.attribute( QStringLiteral( 
"id" ) );
 
   67   QDomElement symmetricModeElem = element.firstChildElement( QStringLiteral( 
"symmetricMode" ) );
 
   68   if ( !symmetricModeElem.isNull() )
 
   70     bool symmetricEnabled = symmetricModeElem.attribute( QStringLiteral( 
"enabled" ) ).toInt() == 1;
 
   71     double symmetricPoint = symmetricModeElem.attribute( QStringLiteral( 
"symmetrypoint" ) ).toDouble();
 
   72     bool astride = symmetricModeElem.attribute( QStringLiteral( 
"astride" ) ).toInt() == 1;
 
   77   QDomElement labelFormatElem = element.firstChildElement( QStringLiteral( 
"labelformat" ) );
 
   78   if ( !labelFormatElem.isNull() )
 
   80     QString format = labelFormatElem.attribute( QStringLiteral( 
"format" ), 
"%1" + QStringLiteral( 
" - " ) + 
"%2" );
 
   81     int precision = labelFormatElem.attribute( QStringLiteral( 
"labelprecision" ), QStringLiteral( 
"4" ) ).toInt();
 
   82     bool trimTrailingZeroes = labelFormatElem.attribute( QStringLiteral( 
"trimtrailingzeroes" ), QStringLiteral( 
"false" ) ) == QLatin1String( 
"true" );
 
   89   QDomElement parametersElem = element.firstChildElement( QStringLiteral( 
"parameters" ) );
 
   94   QDomElement extraElem = element.firstChildElement( QStringLiteral( 
"extraInformation" ) );
 
   95   if ( !extraElem.isNull() )
 
   96     method->
readXml( extraElem, context );
 
  103   QDomElement methodElem = doc.createElement( QStringLiteral( 
"classificationMethod" ) );
 
  105   methodElem.setAttribute( QStringLiteral( 
"id" ), 
id() );
 
  108   QDomElement symmetricModeElem = doc.createElement( QStringLiteral( 
"symmetricMode" ) );
 
  110   symmetricModeElem.setAttribute( QStringLiteral( 
"symmetrypoint" ), 
symmetryPoint() );
 
  111   symmetricModeElem.setAttribute( QStringLiteral( 
"astride" ), mSymmetryAstride ? 1 : 0 );
 
  112   methodElem.appendChild( symmetricModeElem );
 
  115   QDomElement labelFormatElem = doc.createElement( QStringLiteral( 
"labelFormat" ) );
 
  116   labelFormatElem.setAttribute( QStringLiteral( 
"format" ), 
labelFormat() );
 
  117   labelFormatElem.setAttribute( QStringLiteral( 
"labelprecision" ), 
labelPrecision() );
 
  119   methodElem.appendChild( labelFormatElem );
 
  122   QDomElement parametersElem = doc.createElement( QStringLiteral( 
"parameters" ) );
 
  124   methodElem.appendChild( parametersElem );
 
  127   QDomElement extraElem = doc.createElement( QStringLiteral( 
"extraInformation" ) );
 
  129   methodElem.appendChild( extraElem );
 
  137   mSymmetricEnabled = enabled;
 
  139   mSymmetryAstride = astride;
 
  147   mLabelNumberScale = 1.0;
 
  148   mLabelNumberSuffix.clear();
 
  152     mLabelNumberScale /= 10.0;
 
  153     mLabelNumberSuffix.append( 
'0' );
 
  159   static const QRegularExpression RE_TRAILING_ZEROES = QRegularExpression( 
"[.,]?0*$" );
 
  160   static const QRegularExpression RE_NEGATIVE_ZERO = QRegularExpression( 
"^\\-0(?:[.,]0*)?$" );
 
  161   if ( mLabelPrecision > 0 )
 
  163     QString valueStr = QLocale().toString( value, 
'f', mLabelPrecision );
 
  164     if ( mLabelTrimTrailingZeroes )
 
  165       valueStr = valueStr.remove( RE_TRAILING_ZEROES );
 
  166     if ( RE_NEGATIVE_ZERO.match( valueStr ).hasMatch() )
 
  167       valueStr = valueStr.mid( 1 );
 
  172     QString valueStr = QLocale().toString( value * mLabelNumberScale, 
'f', 0 );
 
  173     if ( valueStr == QLatin1String( 
"-0" ) )
 
  175     if ( valueStr != QLatin1String( 
"0" ) )
 
  176       valueStr = valueStr + mLabelNumberSuffix;
 
  183   mParameters.append( definition );
 
  190     if ( def->name() == parameterName )
 
  199   mParameterValues = values;
 
  200   for ( 
auto it = mParameterValues.constBegin(); it != mParameterValues.constEnd(); ++it )
 
  211   if ( expression.isEmpty() )
 
  212     return QList<QgsClassificationRange>();
 
  217   QList<double> values;
 
  228     if ( !ok || values.isEmpty() )
 
  229       return QList<QgsClassificationRange>();
 
  231     auto result = std::minmax_element( values.begin(), values.end() );
 
  232     minimum = *result.first;
 
  233     maximum = *result.second;
 
  240     minimum = minVal.toDouble();
 
  241     maximum = maxVal.toDouble();
 
  245   QList<double> breaks = calculateBreaks( minimum, maximum, values, nclasses );
 
  246   breaks.insert( 0, minimum );
 
  248   return breaksToClasses( breaks );
 
  253   auto result = std::minmax_element( values.begin(), values.end() );
 
  254   double minimum = *result.first;
 
  255   double maximum = *result.second;
 
  258   QList<double> breaks = calculateBreaks( minimum, maximum, values, nclasses );
 
  259   breaks.insert( 0, minimum );
 
  261   return breaksToClasses( breaks );
 
  268     QgsDebugMsg( QStringLiteral( 
"The classification method %1 tries to calculate classes without values while they are required." ).arg( 
name() ) );
 
  272   QList<double> breaks = calculateBreaks( minimum, maximum, QList<double>(), nclasses );
 
  273   breaks.insert( 0, minimum );
 
  275   return breaksToClasses( breaks );
 
  278 QList<QgsClassificationRange> QgsClassificationMethod::breaksToClasses( 
const QList<double> &breaks )
 const 
  280   QList<QgsClassificationRange> 
classes;
 
  282   for ( 
int i = 1; i < breaks.count(); i++ )
 
  285     const double lowerValue = breaks.at( i - 1 );
 
  286     const double upperValue = breaks.at( i );
 
  291     else if ( i == breaks.count() - 1 )
 
  294     QString label = 
labelForRange( lowerValue, upperValue, pos );
 
  308   if ( breaks.count() < 2 )
 
  311   std::sort( breaks.begin(), breaks.end() );
 
  313   double distBelowSymmetricValue = std::fabs( breaks[0] - 
symmetryPoint );
 
  314   double distAboveSymmetricValue = std::fabs( breaks[ breaks.size() - 2 ] - 
symmetryPoint ) ;
 
  315   double absMin = std::min( distAboveSymmetricValue, distBelowSymmetricValue );
 
  318   for ( 
int i = 0; i <= breaks.size() - 2; ++i )
 
  321     if ( std::fabs( breaks.at( i ) - 
symmetryPoint ) >= ( absMin - std::fabs( breaks[0] - breaks[1] ) / 100. ) )
 
  323       breaks.removeAt( i );
 
  343   const QString lowerLabel = valueToLabel( lowerValue );
 
  344   const QString upperLabel = valueToLabel( upperValue );
 
  346   return labelFormat().arg( lowerLabel, upperLabel );