QGIS/src/core/symbology/classification/qgsclassificationequalinterval.cpp
2019-08-30 15:35:53 +02:00

100 lines
3.1 KiB
C++

/***************************************************************************
qgsclassificationequalinterval.h
---------------------
begin : September 2019
copyright : (C) 2019 by Denis Rouzaud
email : denis@opengis.ch
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <QObject>
#include "qgsclassificationequalinterval.h"
const QString QgsClassificationEqualInterval::METHOD_ID = QStringLiteral( "EqualInterval" );
QgsClassificationEqualInterval::QgsClassificationEqualInterval()
: QgsClassificationMethod( false /*valuesRequired*/,
true /*symmetricMode*/,
0 /*codeComplexity*/ )
{
}
QString QgsClassificationEqualInterval::name() const
{
return QObject::tr( "Equal Interval" );
}
QString QgsClassificationEqualInterval::id() const
{
return METHOD_ID;
}
QList<double> QgsClassificationEqualInterval::calculateBreaks( double minimum, double maximum,
const QList<double> &values, int nclasses )
{
Q_UNUSED( values )
// Equal interval algorithm
// Returns breaks based on dividing the range ('minimum' to 'maximum') into 'classes' parts.
QList<double> breaks;
if ( !symmetricModeEnabled() ) // normal mode
{
double step = ( maximum - minimum ) / nclasses;
double value = minimum;
breaks.reserve( nclasses );
for ( int i = 0; i < nclasses; i++ )
{
value += step;
breaks << value;
}
// floating point arithmetics is not precise:
// set the last break to be exactly maximum so we do not miss it
breaks[nclasses - 1] = maximum;
}
else // symmetric mode
{
double distBelowSymmetricValue = std::abs( minimum - symmetryPoint() );
double distAboveSymmetricValue = std::abs( maximum - symmetryPoint() ) ;
if ( symmetryAstride() )
{
if ( nclasses % 2 == 0 ) // we want odd number of classes
++nclasses;
}
else
{
if ( nclasses % 2 == 1 ) // we want even number of classes
++nclasses;
}
double step = 2 * std::min( distBelowSymmetricValue, distAboveSymmetricValue ) / nclasses;
breaks.reserve( nclasses );
double value = ( distBelowSymmetricValue < distAboveSymmetricValue ) ? minimum : maximum - nclasses * step;
for ( int i = 0; i < nclasses; i++ )
{
value += step;
breaks << value;
}
breaks[nclasses - 1] = maximum;
}
return breaks;
}
QgsClassificationMethod *QgsClassificationEqualInterval::clone() const
{
QgsClassificationEqualInterval *c = new QgsClassificationEqualInterval();
copyBase( c );
return c;
}