#include "plot.h" class MyZoomer: public QwtPlotZoomer { public: MyZoomer(QwtPlotCanvas *canvas): QwtPlotZoomer(canvas) { setTrackerMode(AlwaysOn); } virtual QwtText trackerText(const QwtDoublePoint &pos) const { QColor bg(Qt::white); #if QT_VERSION >= 0x040300 bg.setAlpha(200); #endif QwtText text = QwtPlotZoomer::trackerText(pos); text.setBackgroundBrush( QBrush( bg )); return text; } }; class EDepthScaleDraw: public QwtScaleDraw { public: EDepthScaleDraw( MatrixData* d, PlotOptions* p ) { data = d; plot = p; } virtual QwtText label(double v) const { // Send getDepthScaleVal the pixel tick mark value, and get the scaled value. // Send a negative v value because the axes values are backwards, since we want 0 to be at the top. double depth = data->getDepthScaleVal( plot->dataType, plot->depthType, -v ); // Apply the user defined offset value. if( plot->dataType != 1 ) { if( plot->depthType == 0 ) { depth -= ( plot->airOffset / 1000.0 ); } else if( plot->depthType == 1 ) { depth -= ( plot->iceOffset / 1000.0 ); } else if( plot->depthType == 2 ) { depth -= plot->timeOffset; } } // Convert the double to a QString, as the label is a string. QString s; s.sprintf( "%.2f", depth ); return s; } private: MatrixData* data; PlotOptions* plot; }; class ETraceScaleDraw: public QwtScaleDraw { public: ETraceScaleDraw( MatrixData* d, PlotOptions* p ) { data = d; plot = p; } virtual QwtText label( double v ) const { long int trace; /*if( data->getColumnNum() > TRACELENGTH+1 ) { trace = data->getColumnNum() - TRACELENGTH - 1 + v; } else { trace = v; }*/ trace = data->getColumnNum() - TRACELENGTH + v; QString s; s.sprintf( "%li", trace ); return s; } private: MatrixData* data; PlotOptions* plot; }; class EchogramData: public QwtRasterData { private: long int start; int xLen; PlotOptions* parameters; MatrixData* uavData; public: EchogramData( PlotOptions* pVals, MatrixData* d, int xStart, int xLength ) { xLen = xLength; setBoundingRect( QwtDoubleRect( xStart, -( d->getColumnLen()-1 ), xLen, ( d->getColumnLen()-1 ) ) ); start = xStart; uavData = d; parameters = pVals; } virtual QwtRasterData *copy() const { return new EchogramData( parameters, uavData, start, xLen ); } virtual QwtDoubleInterval range() const { return QwtDoubleInterval( parameters->getMinColorMap(), parameters->getMaxColorMap() ); } virtual double value(double x, double y) const { long int yMax; long int yScaled; //if( x < uavData->getColumnNum() ) //{ yMax = uavData->getColumnLen()-1; yScaled = y + yMax; //} /*else { return parameters->getMinColorMap(); }*/ if( ( x > TRACELENGTH ) || ( yScaled > yMax ) || ( x < 0 ) || ( yScaled < 0 ) ) //Coordinate is outside the range of the 2D Vector. { return parameters->getMinColorMap(); } else { return uavData->getMatrixData( x, yMax-yScaled, parameters->dataScale, parameters->dataType, parameters ); } } }; Plot::Plot( PlotOptions* p, QWidget *parent, MatrixData* data ):QwtPlot( parent ) { xLen = p->xWidth; params = p; d = data; panner = NULL; zoomer = NULL; setEchogram(); } void Plot::redraw() { setAxisScaleDraw( QwtPlot::xBottom, new ETraceScaleDraw( d, params ) ); replot(); } void Plot::setEchogram() { d_echogram = new QwtPlotSpectrogram(); colorMap = QwtLinearColorMap( Qt::darkBlue, Qt::red ); colorMap.addColorStop( 0.25, Qt::cyan ); colorMap.addColorStop( 0.75, Qt::yellow ); d_echogram->setColorMap( colorMap ); d_echogram->setData( EchogramData( params, d, 0, TRACELENGTH ) ); d_echogram->attach( this ); // A color bar on the right axis rightAxis = axisWidget( QwtPlot::yRight ); rightAxis->setColorBarEnabled( true ); rightAxis->setColorMap( d_echogram->data().range(), d_echogram->colorMap() ); setAxisScale( QwtPlot::yRight, d_echogram->data().range().minValue(), d_echogram->data().range().maxValue(), params->getIntervalColorMap() ); enableAxis( QwtPlot::yRight ); setAxis(); plotLayout()->setAlignCanvasToScales( true ); setZoom(); // Show the Echogram d_echogram->setDisplayMode( QwtPlotSpectrogram::ImageMode, true ); replot(); } void Plot::reset() { setEchogram(); } void Plot::setZoom() { // LeftButton for the zooming // MidButton for the panning // RightButton: zoom out by 1 // Ctrl+RighButton: zoom out to full size if( zoomer ) { delete zoomer; zoomer = NULL; } zoomer = new MyZoomer(canvas()); zoomer->setMousePattern( QwtEventPattern::MouseSelect2, Qt::RightButton, Qt::ControlModifier ); zoomer->setMousePattern( QwtEventPattern::MouseSelect3, Qt::RightButton ); if( panner ) { delete panner; panner = NULL; } panner = new QwtPlotPanner( canvas() ); panner->setAxisEnabled( QwtPlot::yRight, false ); panner->setMouseButton( Qt::MidButton ); // Avoid jumping when labels with more/less digits // appear/disappear when scrolling vertically const QFontMetrics fm(axisWidget(QwtPlot::yLeft)->font()); QwtScaleDraw *sd = axisScaleDraw(QwtPlot::yLeft); sd->setMinimumExtent( fm.width("100.00") ); const QColor c(Qt::darkBlue); zoomer->setRubberBandPen(c); zoomer->setTrackerPen(c); } void Plot::setAxis() { // Set up the range of values for the yLeft and xBottom axes, as well as the objects to scale the values. setAxisScale( QwtPlot::yLeft, ( d->getColumnLen( params->dataType )-2*d->getColumnLen( params->dataType )+1 ), 0 ); setAxisScaleDraw( QwtPlot::yLeft, new EDepthScaleDraw( d, params ) ); setAxisTitle( QwtPlot::xBottom, "Range Bins or Traces" ); setAxisScale( QwtPlot::xBottom, 0, TRACELENGTH ); setAxisScaleDraw( QwtPlot::xBottom, new ETraceScaleDraw( d, params ) ); // Set the title for the yLeft axis. if( params->dataScale == 1 ) { rightAxis->setTitle( "Signal Returned Power (dB)" ); } else { rightAxis->setTitle( "Amplitude" ); } // Set the axis title for xBottom. if( params->dataType == 1 ) { setAxisTitle( QwtPlot::yLeft, "Frequency (MHz)" ); } else if( params->depthType == 2 ) { setAxisTitle( QwtPlot::yLeft, "Time (us)" ); } else { setAxisTitle( QwtPlot::yLeft, "Depth (km)"); } }