qwt_plot_rescaler.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_rescaler.h"
11 #include "qwt_plot.h"
12 #include "qwt_scale_div.h"
13 #include "qwt_interval.h"
14 #include "qwt_plot_canvas.h"
15 
16 #include <qevent.h>
17 
19 {
20  public:
21  AxisData()
22  : aspectRatio( 1.0 )
24  {
25  }
26 
27  double aspectRatio;
30  mutable QwtScaleDiv scaleDiv;
31 };
32 
34 {
35  public:
39  , isEnabled( false )
40  , inReplot( 0 )
41  {
42  }
43 
45  {
46  if ( !QwtAxis::isValid( axisId ) )
47  return NULL;
48 
49  return &m_axisData[ axisId];
50  }
51 
54  bool isEnabled;
55 
56  mutable int inReplot;
57 
58  private:
60 };
61 
72  QwtAxisId referenceAxis, RescalePolicy policy )
73  : QObject( canvas )
74 {
75  m_data = new PrivateData;
77  m_data->rescalePolicy = policy;
78 
79  setEnabled( true );
80 }
81 
84 {
85  delete m_data;
86 }
87 
98 {
99  if ( m_data->isEnabled != on )
100  {
101  m_data->isEnabled = on;
102 
103  QWidget* w = canvas();
104  if ( w )
105  {
106  if ( m_data->isEnabled )
107  w->installEventFilter( this );
108  else
109  w->removeEventFilter( this );
110  }
111  }
112 }
113 
119 {
120  return m_data->isEnabled;
121 }
122 
130 {
131  m_data->rescalePolicy = policy;
132 }
133 
139 {
140  return m_data->rescalePolicy;
141 }
142 
150 {
151  m_data->referenceAxis = axisId;
152 }
153 
159 {
160  return m_data->referenceAxis;
161 }
162 
170  ExpandingDirection direction )
171 {
172  for ( int axis = 0; axis < QwtAxis::AxisPositions; axis++ )
173  setExpandingDirection( axis, direction );
174 }
175 
184  QwtAxisId axisId, ExpandingDirection direction )
185 {
186  if ( AxisData* axisData = m_data->axisData( axisId ) )
187  axisData->expandingDirection = direction;
188 }
189 
198 {
199  if ( const AxisData* axisData = m_data->axisData( axisId ) )
200  return axisData->expandingDirection;
201 
202  return ExpandBoth;
203 }
204 
213 {
214  for ( int axis = 0; axis < QwtAxis::AxisPositions; axis++ )
215  setAspectRatio( axis, ratio );
216 }
217 
226 void QwtPlotRescaler::setAspectRatio( QwtAxisId axisId, double ratio )
227 {
228  if ( AxisData* axisData = m_data->axisData( axisId ) )
229  {
230  if ( ratio < 0.0 )
231  ratio = 0.0;
232 
233  axisData->aspectRatio = ratio;
234  }
235 }
236 
244 {
245  if ( AxisData* axisData = m_data->axisData( axisId ) )
246  return axisData->aspectRatio;
247 
248  return 0.0;
249 }
250 
262  const QwtInterval& interval )
263 {
264  if ( AxisData* axisData = m_data->axisData( axisId ) )
265  axisData->intervalHint = interval;
266 }
267 
274 {
275  if ( AxisData* axisData = m_data->axisData( axisId ) )
276  return axisData->intervalHint;
277 
278  return QwtInterval();
279 }
280 
283 {
284  return qobject_cast< QWidget* >( parent() );
285 }
286 
288 const QWidget* QwtPlotRescaler::canvas() const
289 {
290  return qobject_cast< const QWidget* >( parent() );
291 }
292 
295 {
296  QWidget* w = canvas();
297  if ( w )
298  w = w->parentWidget();
299 
300  return qobject_cast< QwtPlot* >( w );
301 }
302 
304 const QwtPlot* QwtPlotRescaler::plot() const
305 {
306  const QWidget* w = canvas();
307  if ( w )
308  w = w->parentWidget();
309 
310  return qobject_cast< const QwtPlot* >( w );
311 }
312 
314 bool QwtPlotRescaler::eventFilter( QObject* object, QEvent* event )
315 {
316  if ( object && object == canvas() )
317  {
318  switch ( event->type() )
319  {
320  case QEvent::Resize:
321  {
322  canvasResizeEvent( static_cast< QResizeEvent* >( event ) );
323  break;
324  }
325  case QEvent::PolishRequest:
326  {
327  rescale();
328  break;
329  }
330  default:;
331  }
332  }
333 
334  return false;
335 }
336 
343 void QwtPlotRescaler::canvasResizeEvent( QResizeEvent* event )
344 {
345  const QMargins m = canvas()->contentsMargins();
346  const QSize marginSize( m.left() + m.right(), m.top() + m.bottom() );
347 
348  const QSize newSize = event->size() - marginSize;
349  const QSize oldSize = event->oldSize() - marginSize;
350 
351  rescale( oldSize, newSize );
352 }
353 
356 {
357  const QSize size = canvas()->contentsRect().size();
358  rescale( size, size );
359 }
360 
368  const QSize& oldSize, const QSize& newSize ) const
369 {
370  if ( newSize.isEmpty() )
371  return;
372 
374  for ( int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
375  {
376  const QwtAxisId axisId( axisPos );
377  intervals[axisPos] = interval( axisId );
378  }
379 
380  const QwtAxisId refAxis = referenceAxis();
381  intervals[refAxis] = expandScale( refAxis, oldSize, newSize );
382 
383  for ( int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
384  {
385  const QwtAxisId axisId( axisPos );
386  if ( aspectRatio( axisId ) > 0.0 && axisId != refAxis )
387  {
388  intervals[axisPos] = syncScale(
389  axisId, intervals[refAxis], newSize );
390  }
391  }
392 
393  updateScales( intervals );
394 }
395 
406  const QSize& oldSize, const QSize& newSize ) const
407 {
408  const QwtInterval oldInterval = interval( axisId );
409 
410  QwtInterval expanded = oldInterval;
411  switch ( rescalePolicy() )
412  {
413  case Fixed:
414  {
415  break; // do nothing
416  }
417  case Expanding:
418  {
419  if ( !oldSize.isEmpty() )
420  {
421  double width = oldInterval.width();
422  if ( orientation( axisId ) == Qt::Horizontal )
423  width *= double( newSize.width() ) / oldSize.width();
424  else
425  width *= double( newSize.height() ) / oldSize.height();
426 
427  expanded = expandInterval( oldInterval,
428  width, expandingDirection( axisId ) );
429  }
430  break;
431  }
432  case Fitting:
433  {
434  double dist = 0.0;
435  for ( int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
436  {
437  const QwtAxisId axisId( axisPos );
438  const double d = pixelDist( axisId, newSize );
439  if ( d > dist )
440  dist = d;
441  }
442  if ( dist > 0.0 )
443  {
444  double width;
445  if ( orientation( axisId ) == Qt::Horizontal )
446  width = newSize.width() * dist;
447  else
448  width = newSize.height() * dist;
449 
450  expanded = expandInterval( intervalHint( axisId ),
451  width, expandingDirection( axisId ) );
452  }
453  break;
454  }
455  }
456 
457  return expanded;
458 }
459 
470  const QwtInterval& reference, const QSize& size ) const
471 {
472  double dist;
473  if ( orientation( referenceAxis() ) == Qt::Horizontal )
474  dist = reference.width() / size.width();
475  else
476  dist = reference.width() / size.height();
477 
478  if ( orientation( axisId ) == Qt::Horizontal )
479  dist *= size.width();
480  else
481  dist *= size.height();
482 
483  dist /= aspectRatio( axisId );
484 
485  QwtInterval intv;
486  if ( rescalePolicy() == Fitting )
487  intv = intervalHint( axisId );
488  else
489  intv = interval( axisId );
490 
491  intv = expandInterval( intv, dist, expandingDirection( axisId ) );
492 
493  return intv;
494 }
495 
500 Qt::Orientation QwtPlotRescaler::orientation( QwtAxisId axisId ) const
501 {
502  return QwtAxis::isYAxis( axisId ) ? Qt::Vertical : Qt::Horizontal;
503 }
504 
510 {
511  if ( !plot()->isAxisValid( axisId ) )
512  return QwtInterval();
513 
514  return plot()->axisScaleDiv( axisId ).interval().normalized();
515 }
516 
527  const QwtInterval& interval, double width,
528  ExpandingDirection direction ) const
529 {
530  QwtInterval expanded = interval;
531 
532  switch ( direction )
533  {
534  case ExpandUp:
535  expanded.setMinValue( interval.minValue() );
536  expanded.setMaxValue( interval.minValue() + width );
537  break;
538 
539  case ExpandDown:
540  expanded.setMaxValue( interval.maxValue() );
541  expanded.setMinValue( interval.maxValue() - width );
542  break;
543 
544  case ExpandBoth:
545  default:
546  expanded.setMinValue( interval.minValue() +
547  interval.width() / 2.0 - width / 2.0 );
548  expanded.setMaxValue( expanded.minValue() + width );
549  }
550  return expanded;
551 }
552 
553 double QwtPlotRescaler::pixelDist( QwtAxisId axisId, const QSize& size ) const
554 {
555  const QwtInterval intv = intervalHint( axisId );
556 
557  double dist = 0.0;
558  if ( !intv.isNull() )
559  {
560  if ( axisId == referenceAxis() )
561  {
562  dist = intv.width();
563  }
564  else
565  {
566  const double r = aspectRatio( axisId );
567  if ( r > 0.0 )
568  dist = intv.width() * r;
569  }
570  }
571 
572  if ( dist > 0.0 )
573  {
574  if ( orientation( axisId ) == Qt::Horizontal )
575  dist /= size.width();
576  else
577  dist /= size.height();
578  }
579 
580  return dist;
581 }
582 
589  QwtInterval intervals[QwtAxis::AxisPositions] ) const
590 {
591  if ( m_data->inReplot >= 5 )
592  {
593  return;
594  }
595 
596  QwtPlot* plt = const_cast< QwtPlot* >( plot() );
597 
598  const bool doReplot = plt->autoReplot();
599  plt->setAutoReplot( false );
600 
601  for ( int axisPos = 0; axisPos < QwtAxis::AxisPositions; axisPos++ )
602  {
603  {
604  const QwtAxisId axisId( axisPos );
605 
606  if ( axisId == referenceAxis() || aspectRatio( axisId ) > 0.0 )
607  {
608  double v1 = intervals[axisPos].minValue();
609  double v2 = intervals[axisPos].maxValue();
610 
611  if ( !plt->axisScaleDiv( axisId ).isIncreasing() )
612  qSwap( v1, v2 );
613 
614  if ( m_data->inReplot >= 1 )
615  m_data->axisData( axisId )->scaleDiv = plt->axisScaleDiv( axisId );
616 
617  if ( m_data->inReplot >= 2 )
618  {
620  for ( int t = 0; t < QwtScaleDiv::NTickTypes; t++ )
621  ticks[t] = m_data->axisData( axisId )->scaleDiv.ticks( t );
622 
623  plt->setAxisScaleDiv( axisId, QwtScaleDiv( v1, v2, ticks ) );
624  }
625  else
626  {
627  plt->setAxisScale( axisId, v1, v2 );
628  }
629  }
630  }
631  }
632 
633  QwtPlotCanvas* canvas = qobject_cast< QwtPlotCanvas* >( plt->canvas() );
634 
635  bool immediatePaint = false;
636  if ( canvas )
637  {
638  immediatePaint = canvas->testPaintAttribute( QwtPlotCanvas::ImmediatePaint );
639  canvas->setPaintAttribute( QwtPlotCanvas::ImmediatePaint, false );
640  }
641 
642  plt->setAutoReplot( doReplot );
643 
644  m_data->inReplot++;
645  plt->replot();
646  m_data->inReplot--;
647 
648  if ( canvas && immediatePaint )
649  {
650  canvas->setPaintAttribute( QwtPlotCanvas::ImmediatePaint, true );
651  }
652 }
653 
654 #if QWT_MOC_INCLUDE
655 #include "moc_qwt_plot_rescaler.cpp"
656 #endif
QwtPlotRescaler::PrivateData::PrivateData
PrivateData()
Definition: qwt_plot_rescaler.cpp:36
QwtPlotRescaler::setAspectRatio
void setAspectRatio(double ratio)
Definition: qwt_plot_rescaler.cpp:212
sol::reference
basic_reference< false > reference
Definition: forward.hpp:1100
QwtPlotRescaler::setIntervalHint
void setIntervalHint(QwtAxisId, const QwtInterval &)
Definition: qwt_plot_rescaler.cpp:261
QwtAxis::isYAxis
bool isYAxis(int axisPos)
Definition: qwt_axis.h:57
QwtPlotRescaler::AxisData::intervalHint
QwtInterval intervalHint
Definition: qwt_plot_rescaler.cpp:35
QwtPlotRescaler::setExpandingDirection
void setExpandingDirection(ExpandingDirection)
Definition: qwt_plot_rescaler.cpp:169
QwtPlotRescaler::~QwtPlotRescaler
virtual ~QwtPlotRescaler()
Destructor.
Definition: qwt_plot_rescaler.cpp:83
QwtPlotRescaler::ExpandDown
@ ExpandDown
The lower limit of the scale is adjusted.
Definition: qwt_plot_rescaler.h:76
QwtPlotRescaler::AxisData::scaleDiv
QwtScaleDiv scaleDiv
Definition: qwt_plot_rescaler.cpp:37
qwt_scale_div.h
QwtPlotRescaler::setReferenceAxis
void setReferenceAxis(QwtAxisId)
Definition: qwt_plot_rescaler.cpp:149
QwtPlotRescaler::isEnabled
bool isEnabled() const
Definition: qwt_plot_rescaler.cpp:118
QwtInterval::minValue
double minValue() const
Definition: qwt_interval.h:192
QwtPlotRescaler::PrivateData::isEnabled
bool isEnabled
Definition: qwt_plot_rescaler.cpp:54
QwtPlot
A 2-D plotting widget.
Definition: qwt_plot.h:78
QwtInterval::isNull
bool isNull() const
Definition: qwt_interval.h:314
QwtPlot::setAxisScale
void setAxisScale(QwtAxisId, double min, double max, double stepSize=0)
Disable autoscaling and specify a fixed scale for a selected axis.
Definition: qwt_plot_axis.cpp:477
qwt_interval.h
QList< double >
QwtPlot::setAutoReplot
void setAutoReplot(bool=true)
Set or reset the autoReplot option.
Definition: qwt_plot.cpp:310
QwtPlotRescaler::rescalePolicy
RescalePolicy rescalePolicy() const
Definition: qwt_plot_rescaler.cpp:138
QwtPlotRescaler::QwtPlotRescaler
QwtPlotRescaler(QWidget *canvas, QwtAxisId referenceAxis=QwtAxis::XBottom, RescalePolicy=Expanding)
Definition: qwt_plot_rescaler.cpp:71
QwtPlotRescaler::PrivateData::axisData
QwtPlotRescaler::AxisData * axisData(QwtAxisId axisId)
Definition: qwt_plot_rescaler.cpp:44
QwtPlotRescaler::canvasResizeEvent
virtual void canvasResizeEvent(QResizeEvent *)
Definition: qwt_plot_rescaler.cpp:343
QwtPlotRescaler::Fitting
@ Fitting
Definition: qwt_plot_rescaler.h:63
QwtScaleDiv::ticks
QList< double > ticks(int tickType) const
Definition: qwt_scale_div.cpp:309
QwtPlotRescaler::PrivateData::inReplot
int inReplot
Definition: qwt_plot_rescaler.cpp:56
nonstd::span_lite::size
span_constexpr std::size_t size(span< T, Extent > const &spn)
Definition: span.hpp:1554
QwtPlotRescaler::plot
QwtPlot * plot()
Definition: qwt_plot_rescaler.cpp:294
QwtPlotRescaler::RescalePolicy
RescalePolicy
Definition: qwt_plot_rescaler.h:40
QwtInterval
A class representing an interval.
Definition: qwt_interval.h:22
QwtScaleDiv::NTickTypes
@ NTickTypes
Number of valid tick types.
Definition: qwt_scale_div.h:52
QwtPlotRescaler::rescale
void rescale() const
Adjust the plot axes scales.
Definition: qwt_plot_rescaler.cpp:355
QwtPlotRescaler
QwtPlotRescaler takes care of fixed aspect ratios for plot scales.
Definition: qwt_plot_rescaler.h:29
QwtScaleDiv::isIncreasing
bool isIncreasing() const
Check if the scale division is increasing( lowerBound() <= upperBound() )
Definition: qwt_scale_div.cpp:201
QwtInterval::width
double width() const
Return the width of an interval.
Definition: qwt_interval.h:227
QwtPlotRescaler::interval
QwtInterval interval(QwtAxisId) const
Definition: qwt_plot_rescaler.cpp:509
qwt_plot_rescaler.h
d
d
QwtPlotRescaler::intervalHint
QwtInterval intervalHint(QwtAxisId) const
Definition: qwt_plot_rescaler.cpp:273
QwtPlot::autoReplot
bool autoReplot
Definition: qwt_plot.h:85
QwtPlotRescaler::eventFilter
virtual bool eventFilter(QObject *, QEvent *) QWT_OVERRIDE
Event filter for the plot canvas.
Definition: qwt_plot_rescaler.cpp:314
QwtPlot::axisScaleDiv
const QwtScaleDiv & axisScaleDiv(QwtAxisId) const
Return the scale division of a specified axis.
Definition: qwt_plot_axis.cpp:283
QwtPlotRescaler::PrivateData::m_axisData
QwtPlotRescaler::AxisData m_axisData[QwtAxis::AxisPositions]
Definition: qwt_plot_rescaler.cpp:59
QwtAxisId
int QwtAxisId
Axis identifier.
Definition: qwt_axis_id.h:26
QwtPlotRescaler::ExpandUp
@ ExpandUp
The upper limit of the scale is adjusted.
Definition: qwt_plot_rescaler.h:73
QwtPlot::setAxisScaleDiv
void setAxisScaleDiv(QwtAxisId, const QwtScaleDiv &)
Disable autoscaling and specify a fixed scale for a selected axis.
Definition: qwt_plot_axis.cpp:506
QwtPlotRescaler::syncScale
virtual QwtInterval syncScale(QwtAxisId, const QwtInterval &reference, const QSize &size) const
Definition: qwt_plot_rescaler.cpp:469
QwtPlotRescaler::ExpandBoth
@ ExpandBoth
Both limits of the scale are adjusted.
Definition: qwt_plot_rescaler.h:79
QwtPlotRescaler::m_data
PrivateData * m_data
Definition: qwt_plot_rescaler.h:140
QwtInterval::setMinValue
void setMinValue(double)
Definition: qwt_interval.h:176
QwtPlotRescaler::ExpandingDirection
ExpandingDirection
Definition: qwt_plot_rescaler.h:70
QwtPlotRescaler::expandingDirection
ExpandingDirection expandingDirection(QwtAxisId) const
Definition: qwt_plot_rescaler.cpp:197
QwtAxis::AxisPositions
@ AxisPositions
Definition: qwt_axis.h:44
QwtPlotRescaler::AxisData::expandingDirection
QwtPlotRescaler::ExpandingDirection expandingDirection
Definition: qwt_plot_rescaler.cpp:36
QwtPlotRescaler::PrivateData
Definition: qwt_plot_rescaler.cpp:33
QwtPlotRescaler::PrivateData::rescalePolicy
RescalePolicy rescalePolicy
Definition: qwt_plot_rescaler.cpp:53
QwtPlotRescaler::AxisData::aspectRatio
double aspectRatio
Definition: qwt_plot_rescaler.cpp:34
qwt_plot_canvas.h
QwtPlot::replot
virtual void replot()
Redraw the plot.
Definition: qwt_plot.cpp:545
QwtPlotRescaler::Fixed
@ Fixed
Definition: qwt_plot_rescaler.h:47
QwtPlotRescaler::AxisData
Definition: qwt_plot_rescaler.cpp:18
QwtInterval::normalized
QwtInterval normalized() const
Normalize the limits of the interval.
Definition: qwt_interval.cpp:29
QwtPlotCanvas::ImmediatePaint
@ ImmediatePaint
Definition: qwt_plot_canvas.h:99
QwtPlotCanvas
Canvas of a QwtPlot.
Definition: qwt_plot_canvas.h:29
QwtPlotRescaler::expandInterval
QwtInterval expandInterval(const QwtInterval &, double width, ExpandingDirection) const
Definition: qwt_plot_rescaler.cpp:526
QwtPlotRescaler::referenceAxis
QwtAxisId referenceAxis() const
Definition: qwt_plot_rescaler.cpp:158
QwtInterval::maxValue
double maxValue() const
Definition: qwt_interval.h:198
QwtPlotRescaler::pixelDist
double pixelDist(QwtAxisId, const QSize &) const
Definition: qwt_plot_rescaler.cpp:553
QwtAxis
Definition: qwt_axis.h:18
QwtPlotRescaler::updateScales
virtual void updateScales(QwtInterval intervals[QwtAxis::AxisPositions]) const
Definition: qwt_plot_rescaler.cpp:588
QwtPlot::canvas
QWidget * canvas()
Definition: qwt_plot.cpp:463
QwtPlotRescaler::PrivateData::referenceAxis
QwtAxisId referenceAxis
Definition: qwt_plot_rescaler.cpp:52
QwtScaleDiv
A class representing a scale division.
Definition: qwt_scale_div.h:33
QwtPlotRescaler::expandScale
virtual QwtInterval expandScale(QwtAxisId, const QSize &oldSize, const QSize &newSize) const
Definition: qwt_plot_rescaler.cpp:405
QwtPlotRescaler::Expanding
@ Expanding
Definition: qwt_plot_rescaler.h:57
QwtPlotRescaler::setEnabled
void setEnabled(bool)
En/disable the rescaler.
Definition: qwt_plot_rescaler.cpp:97
QwtPlotRescaler::AxisData::AxisData
AxisData()
Definition: qwt_plot_rescaler.cpp:28
QwtPlotRescaler::aspectRatio
double aspectRatio(QwtAxisId) const
Definition: qwt_plot_rescaler.cpp:243
QwtScaleDiv::interval
QwtInterval interval() const
Definition: qwt_scale_div.cpp:111
QwtAxis::isValid
bool isValid(int axisPos)
Definition: qwt_axis.h:45
QwtInterval::setMaxValue
void setMaxValue(double)
Definition: qwt_interval.h:186
qwt_plot.h
QwtPlotRescaler::orientation
Qt::Orientation orientation(QwtAxisId) const
Definition: qwt_plot_rescaler.cpp:500
QwtPlotRescaler::canvas
QWidget * canvas()
Definition: qwt_plot_rescaler.cpp:282
QwtPlotRescaler::setRescalePolicy
void setRescalePolicy(RescalePolicy)
Definition: qwt_plot_rescaler.cpp:129
QwtAxis::XBottom
@ XBottom
X axis below the canvas.
Definition: qwt_axis.h:44


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Nov 11 2024 03:23:46