Branch data Line data Source code
1 : : /*************************************************************************** 2 : : qgshistogram.cpp 3 : : ---------------- 4 : : begin : May 2015 5 : : copyright : (C) 2015 by Nyall Dawson 6 : : email : nyall dot dawson at gmail dot com 7 : : ***************************************************************************/ 8 : : 9 : : /*************************************************************************** 10 : : * * 11 : : * This program is free software; you can redistribute it and/or modify * 12 : : * it under the terms of the GNU General Public License as published by * 13 : : * the Free Software Foundation; either version 2 of the License, or * 14 : : * (at your option) any later version. * 15 : : * * 16 : : ***************************************************************************/ 17 : : 18 : : #include "qgshistogram.h" 19 : : 20 : : #include "qgsstatisticalsummary.h" 21 : : #include "qgsvectorlayer.h" 22 : : #include "qgsvectorlayerutils.h" 23 : : 24 : 0 : void QgsHistogram::prepareValues() 25 : : { 26 : 0 : std::sort( mValues.begin(), mValues.end() ); 27 : : 28 : 0 : QgsStatisticalSummary s; 29 : 0 : s.setStatistics( QgsStatisticalSummary::Max | QgsStatisticalSummary::Min | QgsStatisticalSummary::InterQuartileRange ); 30 : 0 : s.calculate( mValues ); 31 : 0 : mMin = s.min(); 32 : 0 : mMax = s.max(); 33 : 0 : mIQR = s.interQuartileRange(); 34 : 0 : } 35 : : 36 : 0 : void QgsHistogram::setValues( const QList<double> &values ) 37 : : { 38 : 0 : mValues = values; 39 : 0 : prepareValues(); 40 : 0 : } 41 : : 42 : 0 : bool QgsHistogram::setValues( const QgsVectorLayer *layer, const QString &fieldOrExpression, QgsFeedback *feedback ) 43 : : { 44 : 0 : mValues.clear(); 45 : 0 : if ( !layer ) 46 : 0 : return false; 47 : : 48 : : bool ok; 49 : 0 : mValues = QgsVectorLayerUtils::getDoubleValues( layer, fieldOrExpression, ok, false, nullptr, feedback ); 50 : 0 : if ( !ok ) 51 : 0 : return false; 52 : : 53 : 0 : prepareValues(); 54 : 0 : return true; 55 : 0 : } 56 : : 57 : 0 : double QgsHistogram::optimalBinWidth() const 58 : : { 59 : : //Freedman-Diaconis rule 60 : 0 : return 2.0 * mIQR * std::pow( mValues.count(), -1 / 3.0 ); 61 : : } 62 : : 63 : 0 : int QgsHistogram::optimalNumberBins() const 64 : : { 65 : 0 : return std::ceil( ( mMax - mMin ) / optimalBinWidth() ); 66 : : } 67 : : 68 : 0 : QList<double> QgsHistogram::binEdges( int bins ) const 69 : : { 70 : 0 : double binWidth = ( mMax - mMin ) / bins; 71 : : 72 : 0 : QList<double> edges; 73 : 0 : edges.reserve( bins + 1 ); 74 : 0 : edges << mMin; 75 : 0 : double current = mMin; 76 : 0 : for ( int i = 0; i < bins; ++i ) 77 : : { 78 : 0 : current += binWidth; 79 : 0 : edges << current; 80 : 0 : } 81 : 0 : return edges; 82 : 0 : } 83 : : 84 : 0 : QList<int> QgsHistogram::counts( int bins ) const 85 : : { 86 : 0 : QList<double> edges = binEdges( bins ); 87 : : 88 : 0 : QList<int> binCounts; 89 : 0 : binCounts.reserve( bins ); 90 : 0 : int currentValueIndex = 0; 91 : 0 : for ( int i = 0; i < bins; ++i ) 92 : : { 93 : 0 : int count = 0; 94 : 0 : while ( currentValueIndex < mValues.count() && mValues.at( currentValueIndex ) < edges.at( i + 1 ) ) 95 : : { 96 : 0 : count++; 97 : 0 : currentValueIndex++; 98 : 0 : if ( currentValueIndex >= mValues.count() ) 99 : 0 : break; 100 : : } 101 : 0 : binCounts << count; 102 : 0 : } 103 : : 104 : 0 : if ( currentValueIndex < mValues.count() ) 105 : : { 106 : : //last value needs to be added 107 : 0 : binCounts[ bins - 1 ] = binCounts.last() + 1; 108 : 0 : } 109 : : 110 : 0 : return binCounts; 111 : 0 : } 112 : : 113 : :