qwt_plot_zoomer.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  * Qwt Widget Library
3  * Copyright (C) 1997 Josef Wilgen
4  * Copyright (C) 2002 Uwe Rathmann
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the Qwt License, Version 1.0
8  *****************************************************************************/
9 
10 #include "qwt_plot_zoomer.h"
11 #include "qwt_plot.h"
12 #include "qwt_scale_div.h"
13 #include "qwt_scale_map.h"
14 #include "qwt_interval.h"
15 #include "qwt_picker_machine.h"
16 
17 #include <qstack.h>
18 
19 static QwtInterval qwtExpandedZoomInterval( double v1, double v2,
20  double minRange, const QwtTransform* transform )
21 {
22  double min = v1;
23  double max = v2;
24 
25  if ( max - min < minRange )
26  {
27  min = 0.5 * ( min + max - minRange );
28  max = min + minRange;
29 
30  if ( transform )
31  {
32  // f.e the logarithmic scale doesn't allow values
33  // outside [QwtLogTransform::LogMin/QwtLogTransform::LogMax]
34 
35  double minBounded = transform->bounded( min );
36  double maxBounded = transform->bounded( max );
37 
38  if ( minBounded != min )
39  {
40  maxBounded = transform->bounded( minBounded + minRange );
41  }
42  else if ( maxBounded != max )
43  {
44  minBounded = transform->bounded( maxBounded - minRange );
45  }
46 
47  min = minBounded;
48  max = maxBounded;
49  }
50  }
51 
52  return QwtInterval( min, max );
53 }
54 
55 static QRectF qwtExpandedZoomRect( const QRectF& zoomRect, const QSizeF& minSize,
56  const QwtTransform* transformX, const QwtTransform* transformY )
57 {
58  QRectF r = zoomRect;
59 
60  if ( minSize.width() > r.width() )
61  {
63  r.left(), r.right(), minSize.width(), transformX );
64 
65  r.setLeft( intv.minValue() );
66  r.setRight( intv.maxValue() );
67  }
68 
69  if ( minSize.height() > r.height() )
70  {
72  zoomRect.top(), zoomRect.bottom(), minSize.height(), transformY );
73 
74  r.setTop( intv.minValue() );
75  r.setBottom( intv.maxValue() );
76  }
77 
78  return r;
79 }
80 
82 {
83  public:
86 
88 };
89 
109 QwtPlotZoomer::QwtPlotZoomer( QWidget* canvas, bool doReplot )
110  : QwtPlotPicker( canvas )
111 {
112  if ( canvas )
113  init( doReplot );
114 }
115 
134  QWidget* canvas, bool doReplot )
135  : QwtPlotPicker( xAxisId, yAxisId, canvas )
136 {
137  if ( canvas )
138  init( doReplot );
139 }
140 
142 void QwtPlotZoomer::init( bool doReplot )
143 {
144  m_data = new PrivateData;
145 
146  m_data->maxStackDepth = -1;
147 
151 
152  if ( doReplot && plot() ){
153  plot()->replot();
154  }
155 
156  setZoomBase( scaleRect() );
157 }
158 
160 {
161  delete m_data;
162 }
163 
176 {
177  m_data->maxStackDepth = depth;
178 
179  if ( depth >= 0 )
180  {
181  // unzoom if the current depth is below m_data->maxStackDepth
182 
183  const int zoomOut =
184  m_data->zoomStack.count() - 1 - depth; // -1 for the zoom base
185 
186  if ( zoomOut > 0 )
187  {
188  zoom( -zoomOut );
189  for ( int i = m_data->zoomStack.count() - 1;
190  i > int( m_data->zoomRectIndex ); i-- )
191  {
192  ( void )m_data->zoomStack.pop(); // remove trailing rects
193  }
194  }
195  }
196 }
197 
203 {
204  return m_data->maxStackDepth;
205 }
206 
214 {
215  return m_data->zoomStack;
216 }
217 
223 {
224  return m_data->zoomStack[0];
225 }
226 
236 void QwtPlotZoomer::setZoomBase( bool doReplot )
237 {
238  QwtPlot* plt = plot();
239  if ( plt == NULL )
240  return;
241 
242  if ( doReplot )
243  plt->replot();
244 
245  m_data->zoomStack.clear();
246  m_data->zoomStack.push( scaleRect() );
247  m_data->zoomRectIndex = 0;
248 
249  rescale();
250 }
251 
262 void QwtPlotZoomer::setZoomBase( const QRectF& base )
263 {
264  const QwtPlot* plt = plot();
265  if ( !plt )
266  return;
267 
268  const QRectF sRect = scaleRect();
269  const QRectF bRect = base | sRect;
270 
271  m_data->zoomStack.clear();
272  m_data->zoomStack.push( bRect );
273  m_data->zoomRectIndex = 0;
274 
275  if ( base != sRect )
276  {
277  m_data->zoomStack.push( sRect );
279  }
280 
281  rescale();
282 }
283 
289 {
291 }
292 
297 {
298  return m_data->zoomRectIndex;
299 }
300 
311 void QwtPlotZoomer::zoom( const QRectF& rect )
312 {
313  if ( m_data->maxStackDepth >= 0 &&
315  {
316  return;
317  }
318 
319  const QRectF zoomRect = rect.normalized();
320  if ( zoomRect != m_data->zoomStack[m_data->zoomRectIndex] )
321  {
322  for ( uint i = m_data->zoomStack.count() - 1;
323  i > m_data->zoomRectIndex; i-- )
324  {
325  ( void )m_data->zoomStack.pop();
326  }
327 
328  m_data->zoomStack.push( zoomRect );
330 
331  rescale();
332 
333  Q_EMIT zoomed( zoomRect );
334  }
335 }
336 
348 void QwtPlotZoomer::zoom( int offset )
349 {
350  int newIndex;
351 
352  if ( offset == 0 )
353  {
354  newIndex = 0;
355  }
356  else
357  {
358  newIndex = m_data->zoomRectIndex + offset;
359  newIndex = qBound( 0, newIndex, m_data->zoomStack.count() - 1 );
360  }
361 
362  if ( newIndex != static_cast< int >( m_data->zoomRectIndex ) )
363  {
364  m_data->zoomRectIndex = newIndex;
365  rescale();
366  Q_EMIT zoomed( zoomRect() );
367  }
368 }
369 
386 {
387  if ( zoomStack.isEmpty() )
388  return;
389 
390  if ( m_data->maxStackDepth >= 0 &&
391  zoomStack.count() > m_data->maxStackDepth )
392  {
393  return;
394  }
395 
396  if ( zoomRectIndex < 0 || zoomRectIndex > zoomStack.count() )
397  zoomRectIndex = zoomStack.count() - 1;
398 
399  const bool doRescale = zoomStack[zoomRectIndex] != zoomRect();
400 
402  m_data->zoomRectIndex = uint( zoomRectIndex );
403 
404  if ( doRescale )
405  {
406  rescale();
407  Q_EMIT zoomed( zoomRect() );
408  }
409 }
410 
418 {
419  QwtPlot* plt = plot();
420  if ( !plt )
421  return;
422 
423  const QRectF& rect = m_data->zoomStack[m_data->zoomRectIndex];
424  if ( rect != scaleRect() )
425  {
426  const bool doReplot = plt->autoReplot();
427  plt->setAutoReplot( false );
428 
429  double x1 = rect.left();
430  double x2 = rect.right();
431  if ( !plt->axisScaleDiv( xAxis() ).isIncreasing() )
432  qSwap( x1, x2 );
433 
434  plt->setAxisScale( xAxis(), x1, x2 );
435 
436  double y1 = rect.top();
437  double y2 = rect.bottom();
438  if ( !plt->axisScaleDiv( yAxis() ).isIncreasing() )
439  qSwap( y1, y2 );
440 
441  plt->setAxisScale( yAxis(), y1, y2 );
442 
443  plt->setAutoReplot( doReplot );
444 
445  plt->replot();
446  }
447 }
448 
457 {
458  if ( xAxisId != QwtPlotPicker::xAxis() || yAxisId != QwtPlotPicker::yAxis() )
459  {
460  QwtPlotPicker::setAxes( xAxisId, yAxisId );
461  setZoomBase( scaleRect() );
462  }
463 }
464 
476 {
477  if ( mouseMatch( MouseSelect2, me ) )
478  zoom( 0 );
479  else if ( mouseMatch( MouseSelect3, me ) )
480  zoom( -1 );
481  else if ( mouseMatch( MouseSelect6, me ) )
482  zoom( +1 );
483  else
485 }
486 
499 {
500  if ( !isActive() )
501  {
502  if ( keyMatch( KeyUndo, ke ) )
503  zoom( -1 );
504  else if ( keyMatch( KeyRedo, ke ) )
505  zoom( +1 );
506  else if ( keyMatch( KeyHome, ke ) )
507  zoom( 0 );
508  }
509 
511 }
512 
521 void QwtPlotZoomer::moveBy( double dx, double dy )
522 {
523  const QRectF& rect = m_data->zoomStack[m_data->zoomRectIndex];
524  moveTo( QPointF( rect.left() + dx, rect.top() + dy ) );
525 }
526 
535 void QwtPlotZoomer::moveTo( const QPointF& pos )
536 {
537  double x = pos.x();
538  double y = pos.y();
539 
540  if ( x < zoomBase().left() )
541  x = zoomBase().left();
542  if ( x > zoomBase().right() - zoomRect().width() )
543  x = zoomBase().right() - zoomRect().width();
544 
545  if ( y < zoomBase().top() )
546  y = zoomBase().top();
547  if ( y > zoomBase().bottom() - zoomRect().height() )
548  y = zoomBase().bottom() - zoomRect().height();
549 
550  if ( x != zoomRect().left() || y != zoomRect().top() )
551  {
552  m_data->zoomStack[m_data->zoomRectIndex].moveTo( x, y );
553  rescale();
554  }
555 }
556 
568 bool QwtPlotZoomer::accept( QPolygon& pa ) const
569 {
570  if ( pa.count() < 2 )
571  return false;
572 
573  QRect rect = QRect( pa.first(), pa.last() );
574  rect = rect.normalized();
575 
576  const int minSize = 2;
577  if ( rect.width() < minSize && rect.height() < minSize )
578  return false;
579 
580  const int minZoomSize = 11;
581 
582  const QPoint center = rect.center();
583  rect.setSize( rect.size().expandedTo( QSize( minZoomSize, minZoomSize ) ) );
584  rect.moveCenter( center );
585 
586  pa.resize( 2 );
587  pa[0] = rect.topLeft();
588  pa[1] = rect.bottomRight();
589 
590  return true;
591 }
592 
599 {
600  return QSizeF( m_data->zoomStack[0].width() / 10e4,
601  m_data->zoomStack[0].height() / 10e4 );
602 }
603 
611 {
612  if ( m_data->maxStackDepth >= 0 )
613  {
614  if ( m_data->zoomRectIndex >= uint( m_data->maxStackDepth ) )
615  return;
616  }
617 
618  const QSizeF minSize = minZoomSize();
619  if ( minSize.isValid() )
620  {
621  const QSizeF sz =
622  m_data->zoomStack[m_data->zoomRectIndex].size() * 0.9999;
623 
624  if ( minSize.width() >= sz.width() &&
625  minSize.height() >= sz.height() )
626  {
627  return;
628  }
629  }
630 
632 }
633 
644 bool QwtPlotZoomer::end( bool ok )
645 {
646  ok = QwtPlotPicker::end( ok );
647  if ( !ok )
648  return false;
649 
651  if ( !plot )
652  return false;
653 
654  const QPolygon& pa = selection();
655  if ( pa.count() < 2 )
656  return false;
657 
658  QRect rect = QRect( pa.first(), pa.last() );
659  rect = rect.normalized();
660 
661  const QwtScaleMap xMap = plot->canvasMap( xAxis() );
662  const QwtScaleMap yMap = plot->canvasMap( yAxis() );
663 
664  QRectF zoomRect = QwtScaleMap::invTransform( xMap, yMap, rect ).normalized();
665 
666  zoomRect = qwtExpandedZoomRect( zoomRect, minZoomSize(),
667  xMap.transformation(), yMap.transformation() );
668 
669  zoom( zoomRect );
670 
671  return true;
672 }
673 
674 #if QWT_MOC_INCLUDE
675 #include "moc_qwt_plot_zoomer.cpp"
676 #endif
double invTransform(double p) const
virtual void widgetKeyPressEvent(QKeyEvent *)
QwtPlotZoomer(QWidget *, bool doReplot=true)
Create a zoomer for a plot canvas.
void setZoomStack(const QStack< QRectF > &, int zoomRectIndex=-1)
Assign a zoom stack.
virtual void zoom(const QRectF &)
Zoom in.
virtual void widgetKeyPressEvent(QKeyEvent *) QWT_OVERRIDE
void setRubberBand(RubberBand)
Definition: qwt_picker.cpp:289
QwtAxisId xAxis() const
Return x axis.
virtual void widgetMouseReleaseEvent(QMouseEvent *) QWT_OVERRIDE
virtual void begin() QWT_OVERRIDE
lu_byte right
Definition: lparser.c:1227
uint zoomRectIndex() const
A class representing an interval.
Definition: qwt_interval.h:22
virtual void rescale()
double minValue() const
Definition: qwt_interval.h:192
QWidget * canvas()
QwtAxisId yAxis() const
Return y axis.
lu_byte left
Definition: lparser.c:1226
void setTrackerMode(DisplayMode)
Set the display mode of the tracker.
Definition: qwt_picker.cpp:319
QRectF scaleRect() const
void setAutoReplot(bool=true)
Set or reset the autoReplot option.
Definition: qwt_plot.cpp:310
QwtPlot * plot()
virtual void replot()
Redraw the plot.
Definition: qwt_plot.cpp:545
bool isActive() const
const QwtScaleDiv & axisScaleDiv(QwtAxisId) const
Return the scale division of a specified axis.
QRectF zoomRect() const
A 2-D plotting widget.
Definition: qwt_plot.h:78
virtual bool end(bool ok=true) QWT_OVERRIDE
A state machine for rectangle selections.
const QwtTransform * transformation() const
Get the transformation.
bool isIncreasing() const
Check if the scale division is increasing( lowerBound() <= upperBound() )
virtual QSizeF minZoomSize() const
Limit zooming by a minimum rectangle.
Definition: lz4.c:1706
bool autoReplot
Definition: qwt_plot.h:85
bool mouseMatch(MousePatternCode, const QMouseEvent *) const
Compare a mouse event with an event pattern.
virtual void setAxes(QwtAxisId xAxisId, QwtAxisId yAxisId)
void setStateMachine(QwtPickerMachine *)
Definition: qwt_picker.cpp:229
A transformation between coordinate systems.
Definition: qwt_transform.h:35
j template void())
Definition: json.hpp:4061
QwtPlotPicker provides selections on a plot canvas.
int maxStackDepth() const
virtual void setAxes(QwtAxisId xAxis, QwtAxisId yAxis) QWT_OVERRIDE
A scale map.
Definition: qwt_scale_map.h:26
void setMaxStackDepth(int)
Limit the number of recursive zoom operations to depth.
int QwtAxisId
Axis identifier.
Definition: qwt_axis_id.h:26
void moveBy(double dx, double dy)
virtual ~QwtPlotZoomer()
int top(lua_State *L)
Definition: sol.hpp:11684
PrivateData * m_data
static QRectF qwtExpandedZoomRect(const QRectF &zoomRect, const QSizeF &minSize, const QwtTransform *transformX, const QwtTransform *transformY)
virtual void setZoomBase(bool doReplot=true)
A rectangle ( only for QwtPickerMachine::RectSelection )
Definition: qwt_picker.h:142
QRectF zoomBase() const
QPolygon selection() const
Definition: qwt_picker.cpp:792
bool keyMatch(KeyPatternCode, const QKeyEvent *) const
Compare a key event with an event pattern.
static QwtInterval qwtExpandedZoomInterval(double v1, double v2, double minRange, const QwtTransform *transform)
virtual void widgetMouseReleaseEvent(QMouseEvent *)
void setAxisScale(QwtAxisId, double min, double max, double stepSize=0)
Disable autoscaling and specify a fixed scale for a selected axis.
void init(bool doReplot)
Init the zoomer, used by the constructors.
virtual bool end(bool ok=true) QWT_OVERRIDE
virtual bool accept(QPolygon &) const QWT_OVERRIDE
Check and correct a selected rectangle.
virtual QwtScaleMap canvasMap(QwtAxisId) const
Definition: qwt_plot.cpp:800
const QStack< QRectF > & zoomStack() const
virtual void begin()
void zoomed(const QRectF &rect)
virtual void moveTo(const QPointF &)
double maxValue() const
Definition: qwt_interval.h:198
virtual double bounded(double value) const
Display only when the selection is active.
Definition: qwt_picker.h:170


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Jun 19 2023 03:01:39