mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 13:00:26 -04:00 
			
		
		
		
	Spectrum frequency ticks MSB truncation: base algorithm
This commit is contained in:
		
							parent
							
								
									c63834297a
								
							
						
					
					
						commit
						45ef7c5be0
					
				| @ -53,6 +53,7 @@ void SpectrumSettings::resetToDefaults() | ||||
| 	m_displayMaxHold = false; | ||||
| 	m_displayHistogram = false; | ||||
| 	m_displayGrid = false; | ||||
|     m_truncateFreqScale = false; | ||||
| 	m_averagingMode = AvgModeNone; | ||||
| 	m_averagingIndex = 0; | ||||
|     m_averagingValue = 1; | ||||
| @ -130,6 +131,7 @@ QByteArray SpectrumSettings::serialize() const | ||||
|     s.writeS32(45, m_measurementPrecision); | ||||
|     s.writeS32(46, m_measurementCenterFrequencyOffset); | ||||
|     s.writeBool(47, m_findHistogramPeaks); | ||||
|     s.writeBool(58, m_truncateFreqScale); | ||||
|     s.writeS32(100, m_histogramMarkers.size()); | ||||
| 
 | ||||
| 	for (int i = 0; i < m_histogramMarkers.size(); i++) { | ||||
| @ -242,6 +244,7 @@ bool SpectrumSettings::deserialize(const QByteArray& data) | ||||
|         d.readS32(45, &m_measurementPrecision, 1); | ||||
|         d.readS32(46, &m_measurementCenterFrequencyOffset, 0); | ||||
|         d.readBool(47, &m_findHistogramPeaks, false); | ||||
|         d.readBool(48, &m_truncateFreqScale, false); | ||||
| 
 | ||||
| 		int histogramMarkersSize; | ||||
| 		d.readS32(100, &histogramMarkersSize, 0); | ||||
|  | ||||
| @ -107,6 +107,7 @@ public: | ||||
| 	bool m_displayCurrent; | ||||
| 	bool m_displayHistogram; | ||||
| 	bool m_displayGrid; | ||||
|     bool m_truncateFreqScale; | ||||
| 	AveragingMode m_averagingMode; | ||||
| 	int m_averagingIndex; | ||||
| 	unsigned int m_averagingValue; | ||||
|  | ||||
| @ -63,6 +63,7 @@ public: | ||||
|     void setDisplayGrid(bool display) { m_spectrum->setDisplayGrid(display); } | ||||
|     void setDisplayGridIntensity(int intensity) { m_spectrum->setDisplayGridIntensity(intensity); } | ||||
|     void setDisplayTraceIntensity(int intensity) { m_spectrum->setDisplayTraceIntensity(intensity); } | ||||
|     void setFreqScaleTruncationMode(bool mode) { m_spectrum->setFreqScaleTruncationMode(mode); } | ||||
|     void setLinear(bool linear) { m_spectrum->setLinear(linear); } | ||||
|     void setUseCalibration(bool useCalibration) { m_spectrum->setUseCalibration(useCalibration); } | ||||
|     void setMeasurementParams(SpectrumSettings::Measurement measurement, | ||||
|  | ||||
| @ -193,6 +193,7 @@ void GLSpectrumGUI::displaySettings() | ||||
|     ui->invertWaterfall->setChecked(m_settings.m_invertedWaterfall); | ||||
|     ui->grid->setChecked(m_settings.m_displayGrid); | ||||
|     ui->gridIntensity->setSliderPosition(m_settings.m_displayGridIntensity); | ||||
|     ui->truncateScale->setChecked(m_settings.m_truncateFreqScale); | ||||
| 
 | ||||
|     ui->decay->setToolTip(QString("Decay: %1").arg(m_settings.m_decay)); | ||||
|     ui->decayDivisor->setToolTip(QString("Decay divisor: %1").arg(m_settings.m_decayDivisor)); | ||||
| @ -336,6 +337,7 @@ void GLSpectrumGUI::applySpectrumSettings() | ||||
|     m_glSpectrum->setReferenceLevel(refLevel); | ||||
|     m_glSpectrum->setPowerRange(powerRange); | ||||
|     m_glSpectrum->setFPSPeriodMs(m_settings.m_fpsPeriodMs); | ||||
|     m_glSpectrum->setFreqScaleTruncationMode(m_settings.m_truncateFreqScale); | ||||
|     m_glSpectrum->setLinear(m_settings.m_linear); | ||||
|     m_glSpectrum->setUseCalibration(m_settings.m_useCalibration); | ||||
| 
 | ||||
| @ -689,6 +691,13 @@ void GLSpectrumGUI::on_gridIntensity_valueChanged(int index) | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| void GLSpectrumGUI::on_truncateScale_toggled(bool checked) | ||||
| { | ||||
|     m_settings.m_truncateFreqScale = checked; | ||||
|     qDebug("GLSpectrumGUI::on_truncateScale_toggled: m_truncateFreqScale: %s", (m_settings.m_truncateFreqScale ? "on" : "off")); | ||||
|     applySettings(); | ||||
| } | ||||
| 
 | ||||
| void GLSpectrumGUI::on_traceIntensity_valueChanged(int index) | ||||
| { | ||||
|     m_settings.m_displayTraceIntensity = index; | ||||
|  | ||||
| @ -103,6 +103,7 @@ private slots: | ||||
|     void on_spectrogramStyle_currentIndexChanged(int index); | ||||
|     void on_colorMap_currentIndexChanged(int index); | ||||
| 	void on_gridIntensity_valueChanged(int index); | ||||
|     void on_truncateScale_toggled(bool checked); | ||||
| 	void on_traceIntensity_valueChanged(int index); | ||||
| 	void on_averagingMode_currentIndexChanged(int index); | ||||
|     void on_averaging_currentIndexChanged(int index); | ||||
|  | ||||
| @ -88,6 +88,29 @@ | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="ButtonSwitch" name="truncateScale"> | ||||
|        <property name="toolTip"> | ||||
|         <string>Truncate non significant upper digits from frequency scale</string> | ||||
|        </property> | ||||
|        <property name="text"> | ||||
|         <string>Grid</string> | ||||
|        </property> | ||||
|        <property name="icon"> | ||||
|         <iconset resource="../resources/res.qrc"> | ||||
|          <normaloff>:/truncate.png</normaloff>:/truncate.png</iconset> | ||||
|        </property> | ||||
|        <property name="iconSize"> | ||||
|         <size> | ||||
|          <width>16</width> | ||||
|          <height>16</height> | ||||
|         </size> | ||||
|        </property> | ||||
|        <property name="checkable"> | ||||
|         <bool>true</bool> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QPushButton" name="clearSpectrum"> | ||||
|        <property name="sizePolicy"> | ||||
|  | ||||
| @ -492,6 +492,12 @@ void GLSpectrumView::setDisplayTraceIntensity(int intensity) | ||||
|     update(); | ||||
| } | ||||
| 
 | ||||
| void GLSpectrumView::setFreqScaleTruncationMode(bool mode) | ||||
| { | ||||
|     m_frequencyScale.setTruncateMode(mode); | ||||
|     update(); | ||||
| } | ||||
| 
 | ||||
| void GLSpectrumView::setLinear(bool linear) | ||||
| { | ||||
|     m_mutex.lock(); | ||||
|  | ||||
| @ -179,6 +179,7 @@ public: | ||||
|     void setDisplayGrid(bool display); | ||||
|     void setDisplayGridIntensity(int intensity); | ||||
|     void setDisplayTraceIntensity(int intensity); | ||||
|     void setFreqScaleTruncationMode(bool mode); | ||||
|     void setLinear(bool linear); | ||||
|     void setUseCalibration(bool useCalibration); | ||||
|     void setMeasurements(SpectrumMeasurements *measurements) { m_measurements = measurements; } | ||||
|  | ||||
| @ -30,12 +30,18 @@ static double trunc(double d) | ||||
| 
 | ||||
| QString ScaleEngine::formatTick(double value, int decimalPlaces) | ||||
| { | ||||
|     if (m_truncated && (m_physicalUnit != Unit::Scientific)) | ||||
|     { | ||||
|         value = ((value * m_scale) - m_truncationValue) / m_scale; | ||||
|         qDebug("ScaleEngine::formatTick: value: %f decimalPlaces: %d m_scale: %f", value, decimalPlaces, m_scale); | ||||
|     } | ||||
| 
 | ||||
| 	if (m_physicalUnit != Unit::TimeHMS) | ||||
| 	{ | ||||
| 	    if (m_physicalUnit == Unit::Scientific) { | ||||
|             return QString("%1").arg(m_makeOpposite ? -value : value, 0, 'e', m_fixedDecimalPlaces); | ||||
| 	    } else { | ||||
| 	        return QString("%1").arg(m_makeOpposite ? -value : value, 0, 'f', decimalPlaces); | ||||
| 	        return QString("%1%2").arg(m_truncated ? "'" : "").arg(m_makeOpposite ? -value : value, 0, 'f', decimalPlaces); | ||||
| 	    } | ||||
| 	} | ||||
| 	else | ||||
| @ -49,28 +55,41 @@ QString ScaleEngine::formatTick(double value, int decimalPlaces) | ||||
| 		double orig = fabs(actual); | ||||
| 		double tmp; | ||||
| 
 | ||||
| 		if(orig >= 86400.0) { | ||||
|         if (m_truncated) { | ||||
|             str = "'"; | ||||
|         } | ||||
| 
 | ||||
| 		if (orig >= 86400.0) | ||||
|         { | ||||
| 			tmp = floor(actual / 86400.0); | ||||
| 			str = QString("%1.").arg(tmp, 0, 'f', 0); | ||||
| 			str += QString("%1.").arg(tmp, 0, 'f', 0); | ||||
| 			actual -= tmp * 86400.0; | ||||
| 			if(actual < 0.0) | ||||
| 
 | ||||
|         	if (actual < 0.0) { | ||||
| 			    actual *= -1.0; | ||||
|             } | ||||
| 		} | ||||
| 
 | ||||
| 		if(orig >= 3600.0) { | ||||
| 		if (orig >= 3600.0) | ||||
|         { | ||||
| 			tmp = floor(actual / 3600.0); | ||||
| 			str += QString("%1:").arg(tmp, 2, 'f', 0, QChar('0')); | ||||
| 			actual -= tmp * 3600.0; | ||||
| 			if(actual < 0.0) | ||||
| 
 | ||||
|             if (actual < 0.0) { | ||||
| 			    actual *= -1.0; | ||||
|             } | ||||
| 		} | ||||
| 
 | ||||
| 		if(orig >= 60.0) { | ||||
| 		if (orig >= 60.0) | ||||
|         { | ||||
| 			tmp = floor(actual / 60.0); | ||||
| 			str += QString("%1:").arg(tmp, 2, 'f', 0, QChar('0')); | ||||
| 			actual -= tmp * 60.0; | ||||
| 			if(actual < 0.0) | ||||
| 
 | ||||
|             if (actual < 0.0) { | ||||
| 			    actual *= -1.0; | ||||
|             } | ||||
| 		} | ||||
| 
 | ||||
| 		tmp = m_makeOpposite ? -actual : actual; | ||||
| @ -104,8 +123,11 @@ void ScaleEngine::calcScaleFactor() | ||||
| { | ||||
| 	double median, range, freqBase; | ||||
| 
 | ||||
| 	median = ((m_rangeMax - m_rangeMin) / 2.0) + m_rangeMin; | ||||
| 	range = (m_rangeMax - m_rangeMin); | ||||
|     double rangeMin = m_rangeMin; | ||||
|     double rangeMax = m_rangeMax; | ||||
| 
 | ||||
| 	median = ((rangeMax - rangeMin) / 2.0) + rangeMin; | ||||
| 	range = (rangeMax - rangeMin); | ||||
| 	freqBase = (median == 0 ? range : median); | ||||
| 	m_scale = 1.0; | ||||
| 
 | ||||
| @ -361,8 +383,10 @@ void ScaleEngine::reCalc() | ||||
| 	float lastEndPos; | ||||
| 	bool done; | ||||
| 
 | ||||
| 	if(!m_recalc) | ||||
| 	if (!m_recalc) { | ||||
| 		return; | ||||
|     } | ||||
| 
 | ||||
| 	m_recalc = false; | ||||
| 
 | ||||
| 	m_tickList.clear(); | ||||
| @ -391,6 +415,8 @@ void ScaleEngine::reCalc() | ||||
| 
 | ||||
| 	numMajorTicks = (int)((rangeMaxScaled - rangeMinScaled) / m_majorTickValueDistance); | ||||
| 
 | ||||
|     updateTruncation(numMajorTicks); | ||||
| 
 | ||||
| 	if(numMajorTicks == 0) { | ||||
| 		forceTwoTicks(); | ||||
| 		return; | ||||
| @ -518,13 +544,16 @@ ScaleEngine::ScaleEngine() : | ||||
|     m_rangeMin(-1.0), | ||||
|     m_rangeMax(1.0), | ||||
|     m_recalc(true), | ||||
|     m_scale(1.0f), | ||||
|     m_scale(1.0), | ||||
| 	m_majorTickValueDistance(1.0), | ||||
|     m_firstMajorTickValue(1.0), | ||||
|     m_numMinorTicks(1), | ||||
|     m_decimalPlaces(1), | ||||
|     m_fixedDecimalPlaces(2), | ||||
|     m_makeOpposite(false) | ||||
|     m_makeOpposite(false), | ||||
|     m_truncateMode(false), | ||||
|     m_truncated(false), | ||||
|     m_truncationValue(0.0) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| @ -570,7 +599,8 @@ void ScaleEngine::setRange(Unit::Physical physicalUnit, float rangeMin, float ra | ||||
| 	tmpRangeMin = rangeMin; | ||||
| 	tmpRangeMax = rangeMax; | ||||
| 
 | ||||
| 	if((tmpRangeMin != m_rangeMin) || (tmpRangeMax != m_rangeMax) || (m_physicalUnit != physicalUnit)) { | ||||
| 	if ((tmpRangeMin != m_rangeMin) || (tmpRangeMax != m_rangeMax) || (m_physicalUnit != physicalUnit)) | ||||
|     { | ||||
| 		m_physicalUnit = physicalUnit; | ||||
| 		m_rangeMin = tmpRangeMin; | ||||
| 		m_rangeMax = tmpRangeMax; | ||||
| @ -623,3 +653,48 @@ float ScaleEngine::getScaleWidth() | ||||
| 	} | ||||
| 	return max; | ||||
| } | ||||
| 
 | ||||
| void ScaleEngine::setTruncateMode(bool mode) | ||||
| { | ||||
|     qDebug("ScaleEngine::setTruncateMode: %s", (mode ? "on" : "off")); | ||||
|     m_truncateMode = mode; | ||||
|     m_recalc = true; | ||||
|     reCalc(); | ||||
| } | ||||
| 
 | ||||
| void ScaleEngine::updateTruncation(int numMajorTicks) | ||||
| { | ||||
|     m_truncated = false; | ||||
|     m_truncationValue = 0.0; | ||||
| 
 | ||||
|     if (!m_truncateMode) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (order(m_rangeMax) != order(m_rangeMin)) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     double width = m_rangeMax - m_rangeMin; | ||||
|     int widthOrder = order(width); | ||||
|     int maxOrder = order(m_rangeMax); | ||||
| 
 | ||||
|     if ((widthOrder < 0) || (maxOrder < 0) || (widthOrder == maxOrder)) { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     for (int i = widthOrder+1; i <= maxOrder; i++) | ||||
|     { | ||||
|         int irangeMin = floor(m_rangeMin / pow(10, i)); | ||||
|         int irangeMax = floor(m_rangeMin / pow(10, i)); | ||||
| 
 | ||||
|         if (irangeMin == irangeMax) | ||||
|         { | ||||
|             m_truncated = true; | ||||
|             m_truncationValue = irangeMin * pow(10, i); | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     qDebug("ScaleEngine::updateTruncation: m_truncationValue: %f", m_truncationValue); | ||||
| } | ||||
|  | ||||
| @ -19,6 +19,8 @@ | ||||
| #ifndef INCLUDE_SCALEENGINE_H | ||||
| #define INCLUDE_SCALEENGINE_H | ||||
| 
 | ||||
| #include <math.h> | ||||
| 
 | ||||
| #include <QFont> | ||||
| #include <QString> | ||||
| #include <QList> | ||||
| @ -48,6 +50,7 @@ public: | ||||
|     float getRangeMax() const { return m_rangeMax; } | ||||
| 	void setMakeOpposite(bool makeOpposite) { m_makeOpposite = makeOpposite; } | ||||
| 	void setFixedDecimalPlaces(int decimalPlaces) { m_fixedDecimalPlaces =decimalPlaces; } | ||||
|     void setTruncateMode(bool mode); | ||||
| 
 | ||||
| 	float getPosFromValue(double value); | ||||
| 	float getValueFromPos(double pos); | ||||
| @ -65,10 +68,10 @@ private: | ||||
| 	float m_charSize; | ||||
| 
 | ||||
| 	// graph configuration
 | ||||
| 	float m_size; | ||||
| 	double m_size; | ||||
| 	Unit::Physical m_physicalUnit; | ||||
| 	float m_rangeMin; | ||||
| 	float m_rangeMax; | ||||
| 	double m_rangeMin; | ||||
| 	double m_rangeMax; | ||||
| 
 | ||||
| 	// calculated values
 | ||||
| 	bool m_recalc; | ||||
| @ -81,6 +84,9 @@ private: | ||||
| 	int m_decimalPlaces; | ||||
| 	int m_fixedDecimalPlaces; | ||||
| 	bool m_makeOpposite; // will show -value instead of value
 | ||||
|     bool m_truncateMode; //!< truncate upper digits mode
 | ||||
|     bool m_truncated; //!< true if upper digits are truncated
 | ||||
|     double m_truncationValue; //!< value to subreact from tick display values
 | ||||
| 
 | ||||
| 	QString formatTick(double value, int decimalPlaces); | ||||
| 	void calcCharSize(); | ||||
| @ -89,6 +95,11 @@ private: | ||||
| 	int calcTickTextSize(double distance); | ||||
| 	void forceTwoTicks(); | ||||
| 	void reCalc(); | ||||
|     void updateTruncation(int numMajorTicks); | ||||
| 
 | ||||
|     inline int order(double value) { | ||||
|         return floor(log10(value)); | ||||
|     } | ||||
| 
 | ||||
| 	double majorTickValue(int tick); | ||||
| 	double minorTickValue(int tick); | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| <RCC> | ||||
|   <qresource prefix="/"> | ||||
|     <file>truncate.png</file> | ||||
|     <file>caliper.png</file> | ||||
|     <file>flip_windows.png</file> | ||||
|     <file>waterfall_3d.png</file> | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								sdrgui/resources/truncate.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sdrgui/resources/truncate.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 9.1 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sdrgui/resources/truncate.xcf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								sdrgui/resources/truncate.xcf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user