File indexing completed on 2024-12-08 06:35:36
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2011-2012 Florian Eßer <f.esser@rwth-aachen.de> 0004 // 0005 0006 #include "ElevationProfilePlotAxis.h" 0007 0008 #include "MarbleGlobal.h" 0009 #include "MarbleLocale.h" 0010 0011 #include <qmath.h> 0012 0013 namespace Marble 0014 { 0015 0016 ElevationProfilePlotAxis::ElevationProfilePlotAxis() 0017 : m_minValue( 0.0 ), 0018 m_maxValue ( 0.0 ), 0019 m_displayScale( 1.0 ), 0020 m_pixelLength ( 0 ), 0021 m_minTickCount( 2 ), 0022 m_maxTickCount( 5 ), 0023 m_unitString( QString() ) 0024 { 0025 // nothing to do... 0026 } 0027 0028 void ElevationProfilePlotAxis::setRange(qreal minValue, qreal maxValue) 0029 { 0030 m_minValue = minValue; 0031 m_maxValue = maxValue; 0032 update(); 0033 } 0034 0035 void ElevationProfilePlotAxis::setLength(int length) 0036 { 0037 m_pixelLength = length; 0038 update(); 0039 } 0040 0041 void ElevationProfilePlotAxis::setTickCount( const int min, const int max ) 0042 { 0043 m_minTickCount = min; 0044 m_maxTickCount = max; 0045 } 0046 0047 void ElevationProfilePlotAxis::update() 0048 { 0049 updateTicks(); 0050 updateScale(); 0051 } 0052 0053 qreal ElevationProfilePlotAxis::minValue() const 0054 { 0055 return m_minValue; 0056 } 0057 0058 qreal ElevationProfilePlotAxis::maxValue() const 0059 { 0060 return m_maxValue; 0061 } 0062 0063 qreal ElevationProfilePlotAxis::range() const 0064 { 0065 return m_maxValue - m_minValue; 0066 } 0067 0068 qreal ElevationProfilePlotAxis::scale() const 0069 { 0070 return m_displayScale; 0071 } 0072 0073 QString ElevationProfilePlotAxis::unit() const 0074 { 0075 return m_unitString; 0076 } 0077 0078 AxisTickList ElevationProfilePlotAxis::ticks() const 0079 { 0080 return m_ticks; 0081 } 0082 0083 void ElevationProfilePlotAxis::updateTicks() 0084 { 0085 m_ticks.clear(); 0086 if( range() == 0 ) { 0087 return; 0088 } 0089 0090 static QVector<int> niceIntervals = QVector<int>() << 10 << 20 << 25 << 30 << 50; 0091 0092 const int exponent = qRound( log10( range() ) ); 0093 const qreal factor = qPow( 10, 2 - exponent ); 0094 const qreal tickRange = range() * factor; 0095 0096 qreal stepWidth = niceIntervals.last(); 0097 qreal error = tickRange; 0098 for ( const int i: niceIntervals ) { 0099 const qreal numTicks = tickRange / i; 0100 if ( numTicks < m_minTickCount || numTicks > m_maxTickCount ) { 0101 continue; 0102 } 0103 const qreal newError = qAbs( numTicks - qRound( numTicks ) ); 0104 if ( newError < error ) { 0105 error = newError; 0106 stepWidth = i; 0107 } 0108 } 0109 stepWidth /= factor; 0110 0111 qreal offset = 0; 0112 if ( fmod( m_minValue, stepWidth ) != 0 ) { 0113 offset = stepWidth - fmod( m_minValue, stepWidth ); 0114 } 0115 0116 qreal val = m_minValue + offset; 0117 int pos = m_pixelLength / range() * offset; 0118 m_ticks << AxisTick( pos, val ); 0119 while( val < m_maxValue ) { 0120 val += stepWidth; 0121 pos += m_pixelLength / range() * stepWidth; 0122 if ( pos > m_pixelLength ) { 0123 break; 0124 } 0125 m_ticks << AxisTick( pos, val ); 0126 } 0127 } 0128 0129 void ElevationProfilePlotAxis::updateScale() 0130 { 0131 MarbleLocale::MeasurementSystem measurementSystem; 0132 measurementSystem = MarbleGlobal::getInstance()->locale()->measurementSystem(); 0133 switch ( measurementSystem ) { 0134 case MarbleLocale::MetricSystem: 0135 if ( range() >= 10 * KM2METER ) { 0136 m_unitString = tr( "km" ); 0137 m_displayScale = METER2KM; 0138 } else { 0139 m_unitString = tr( "m" ); 0140 m_displayScale = 1.0; 0141 } 0142 break; 0143 case MarbleLocale::ImperialSystem: 0144 // FIXME: Do these values make sense? 0145 if ( range() >= 10 * KM2METER * MI2KM ) { 0146 m_unitString = tr( "mi" ); 0147 m_displayScale = METER2KM * KM2MI; 0148 } else { 0149 m_unitString = tr( "ft" ); 0150 m_displayScale = M2FT; 0151 } 0152 break; 0153 0154 case MarbleLocale::NauticalSystem: 0155 m_unitString = tr("nm"); 0156 m_displayScale = METER2KM * KM2NM; 0157 break; 0158 } 0159 } 0160 0161 } 0162 0163 #include "moc_ElevationProfilePlotAxis.cpp"