PDA

View Full Version : spectrogram with fixed aspect ratio (1:1) and zooming/unzooming



dusan
15th October 2010, 02:26
Hello,

I'd like to plot a spectrogram with fixed aspect ratio (1:1) and have zooming/unzooming feature. I added the following code to the spectrogram example:


QwtPlotRescaler *d_rescaler = new QwtPlotRescaler(canvas());
d_rescaler->setRescalePolicy(QwtPlotRescaler::Fitting);
d_rescaler->setReferenceAxis(QwtPlot::xBottom);
d_rescaler->setAspectRatio(QwtPlot::yLeft, 1.0);
d_rescaler->setAspectRatio(QwtPlot::yRight, 0.0);
d_rescaler->setAspectRatio(QwtPlot::xTop, 0.0);
d_rescaler->setExpandingDirection(QwtPlotRescaler::ExpandBoth) ;
d_rescaler->setIntervalHint(Qt::XAxis, d_spectrogram->data()->interval( Qt::XAxis ));
d_rescaler->setIntervalHint(Qt::YAxis, d_spectrogram->data()->interval( Qt::YAxis ));


When I zoom in selecting a rectangular region the original aspect ratio (1:1)
is not preserved. Also when I resize the window the zoom is not preserved, it gets
unzoomed to original size.

What is the proper way of having a zoom and fixed aspect ratio using spectrogram?

Thanks,
Dusan

nige
12th April 2011, 13:54
Hi Dusan,
Did you ever resolve this issue? If so, could you post your solution? I would like to do the same thing!

dusan
29th December 2011, 21:30
I finally got a chance to try something that will solve my issues with zooming the spectrogram plot and preserving
aspect ratio. My workaround requires modifying two files in qwt library (qwt_plot.h and qwt-plot.cpp). The idea is to
pass the information about the intended aspect ratio (the size of the plot) to the qwt_plot object using on the information
available in the user's application based on the data to be plotted.

Attached are 5 files. If you want to test this replace qwt_plot.h and qwt_plot.cpp in qwt/src and recompile the library, and then replace plot.h and plot.cpp
in examples/spectrogram and recompile the example program. This version of the example program plots the world map in proper aspect ratio
regardless of the application window size or zoom.

I'd like to here if someone has more elegant solution, especially if it doesn't require qwt source code modifications.

Dusan

Uwe
2nd January 2012, 10:16
I'd like to here if someone has more elegant solution, especially if it doesn't require qwt source code modifications.
As far as I can see all what your patch does is to pass a rectangle to be used by the layout system instead of the geometry of the plot widget.

You would have the same effect simply by adjusting the margins ( QWidget::setContentsMargins() ) . Another possible ( IMHO cleaner ) solution is to insert a container widget as parent of the plot widget and to implement its resizeEvent ( setting the geometry of the the plot widget instead of using a QLayout ).

But I believe that you took the wrong approach at all: better manipulate the zoomer to select rectangles for the specific aspect ratio. Have a look at its base classes and you will find many ways to manipulate the selection of the rectangle. F.e. with overloading QwtPlotPicker::move() you could translate the x ( or y coordinate ) so that the rubberband shows the effective zoom rectangle - taking the aspect ratio into count.

Uwe

dusan
3rd January 2012, 15:16
Uwe, thanks for the explanation.



You would have the same effect simply by adjusting the margins ( QWidget::setContentsMargins() ) .


I think I actually tried something like that (using setContentsMargins)
but I think the problem was that the margins need to be reset every time the plot is resized,
and setting the margins in resize event will trigger new resize event. What's the proper place
to set the margins.



But I believe that you took the wrong approach at all: better manipulate the zoomer to select rectangles for the specific aspect ratio. Have a look at its base classes and you will find many ways to manipulate the selection of the rectangle. F.e. with overloading QwtPlotPicker::move() you could translate the x ( or y coordinate ) so that the rubberband shows the effective zoom rectangle - taking the aspect ratio into count.

Unfortunately I think I do not understand how to do this. Would you mind making an example?

Thanks,
Dusan

Uwe
4th January 2012, 08:42
I think I actually tried something like that (using setContentsMargins)
but I think the problem was that the margins need to be reset every time the plot is resized, ...
Yes of course, its not different to your implementation - only a different way to set such a rectangle.

... and setting the margins in resize event will trigger new resize event.
Setting margins to widget triggers resize events for its children ( when they are organized in a layout ) but it shouldn't cause any resize event for the widget itsself - why should it ?

Unfortunately I think I do not understand how to do this.
Study QwtPlotZoomer and its base classes.

Uwe

gavinmagnus
17th November 2016, 17:17
Thread is really old, but here's my solution:



class MyPlotZoomer : public QwtPlotZoomer {

// ...

private:
int zx;
int zy;

protected:
virtual void widgetMousePressEvent(QMouseEvent *me);
virtual void move(const QPoint &p);
};

void MyPlotZoomer::widgetMousePressEvent(QMouseEvent *me)
{
if ( mouseMatch( MouseSelect1, me ) )
{
zx = me->pos().x();
zy = me->pos().y();
}

QwtPlotPicker::widgetMousePressEvent(me);
}

void MyPlotZoomer::move(const QPoint &p)
{
QPoint square;

if( abs( p.x() - zx )
>
abs( p.y() - zy ) )
{
square.setX( p.x() );

if( p.y() > zy )
square.setY( zy + abs( p.x() - zx ) );
else
square.setY( zy - abs( p.x() - zx ) );
}
else
{
square.setY( p.y() );

if( p.x() > zx )
square.setX( zx + abs( p.y() - zy ) );
else
square.setX( zx - abs( p.y() - zy ) );
}

QwtPlotZoomer::move( square );
}

gavinmagnus
18th November 2016, 11:48
Ok, this is bad, I cannot edit my incorrect post. It looks like all you need to do in QWT 6.3 is to overload QwtPlotZoomer::zoom and make it call QwtPlotRescaller::rescale()



class MyPlotZoomer : public QwtPlotZoomer
{
public:
MyPlotZoomer(QwtPlotCanvas* widget, bool doReplot=true);
QwtPlotRescaler * myPlotRescaler;

virtual void zoom(const QRectF& rect);
}

MyPlotZoomer::MyPlotZoomer(QwtPlotCanvas* widget, bool doReplot) :
QwtPlotZoomer(widget, doReplot)
{
myPlotRescaler = new QwtPlotRescaler( widget );
//For example:
myPlotRescaler->setRescalePolicy( QwtPlotRescaler::Expanding );
myPlotRescaler->setExpandingDirection( QwtPlotRescaler::ExpandBoth );
myPlotRescaler->setReferenceAxis(QwtPlot::xBottom);
myPlotRescaler->setAspectRatio(QwtPlot::yLeft, 1.0);
myPlotRescaler->setAspectRatio(QwtPlot::yRight, 0.0);
myPlotRescaler->setAspectRatio(QwtPlot::xTop, 0.0);
}

MyPlotZoomer::zoom(const QRectF& rect)
{
QwtPlotZoomer::zoom(rect);

//Most important
myPlotRescaler->rescale();
}