qwt_plot_rescaler.cpp
Go to the documentation of this file.
1 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
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 #include <qevent.h>
16 #include <qalgorithms.h>
17 
19 {
20 public:
22  aspectRatio( 1.0 ),
24  {
25  }
26 
27  double aspectRatio;
31 };
32 
34 {
35 public:
37  referenceAxis( QwtPlot::xBottom ),
39  isEnabled( false ),
40  inReplot( 0 )
41  {
42  }
43 
47  bool isEnabled;
48 
49  mutable int inReplot;
50 };
51 
62  int referenceAxis, RescalePolicy policy ):
63  QObject( canvas )
64 {
65  d_data = new PrivateData;
67  d_data->rescalePolicy = policy;
68 
69  setEnabled( true );
70 }
71 
74 {
75  delete d_data;
76 }
77 
88 {
89  if ( d_data->isEnabled != on )
90  {
91  d_data->isEnabled = on;
92 
93  QWidget *w = canvas();
94  if ( w )
95  {
96  if ( d_data->isEnabled )
97  w->installEventFilter( this );
98  else
99  w->removeEventFilter( this );
100  }
101  }
102 }
103 
109 {
110  return d_data->isEnabled;
111 }
112 
120 {
121  d_data->rescalePolicy = policy;
122 }
123 
129 {
130  return d_data->rescalePolicy;
131 }
132 
140 {
141  d_data->referenceAxis = axis;
142 }
143 
149 {
150  return d_data->referenceAxis;
151 }
152 
160  ExpandingDirection direction )
161 {
162  for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
163  setExpandingDirection( axis, direction );
164 }
165 
174  int axis, ExpandingDirection direction )
175 {
176  if ( axis >= 0 && axis < QwtPlot::axisCnt )
177  d_data->axisData[axis].expandingDirection = direction;
178 }
179 
188 {
189  if ( axis >= 0 && axis < QwtPlot::axisCnt )
190  return d_data->axisData[axis].expandingDirection;
191 
192  return ExpandBoth;
193 }
194 
203 {
204  for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
205  setAspectRatio( axis, ratio );
206 }
207 
216 void QwtPlotRescaler::setAspectRatio( int axis, double ratio )
217 {
218  if ( ratio < 0.0 )
219  ratio = 0.0;
220 
221  if ( axis >= 0 && axis < QwtPlot::axisCnt )
222  d_data->axisData[axis].aspectRatio = ratio;
223 }
224 
231 double QwtPlotRescaler::aspectRatio( int axis ) const
232 {
233  if ( axis >= 0 && axis < QwtPlot::axisCnt )
234  return d_data->axisData[axis].aspectRatio;
235 
236  return 0.0;
237 }
238 
250  const QwtInterval &interval )
251 {
252  if ( axis >= 0 && axis < QwtPlot::axisCnt )
254 }
255 
262 {
263  if ( axis >= 0 && axis < QwtPlot::axisCnt )
264  return d_data->axisData[axis].intervalHint;
265 
266  return QwtInterval();
267 }
268 
271 {
272  return qobject_cast<QWidget *>( parent() );
273 }
274 
276 const QWidget *QwtPlotRescaler::canvas() const
277 {
278  return qobject_cast<const QWidget *>( parent() );
279 }
280 
283 {
284  QWidget *w = canvas();
285  if ( w )
286  w = w->parentWidget();
287 
288  return qobject_cast<QwtPlot *>( w );
289 }
290 
293 {
294  const QWidget *w = canvas();
295  if ( w )
296  w = w->parentWidget();
297 
298  return qobject_cast<const QwtPlot *>( w );
299 }
300 
302 bool QwtPlotRescaler::eventFilter( QObject *object, QEvent *event )
303 {
304  if ( object && object == canvas() )
305  {
306  switch ( event->type() )
307  {
308  case QEvent::Resize:
309  {
310  canvasResizeEvent( static_cast<QResizeEvent *>( event ) );
311  break;
312  }
313  case QEvent::PolishRequest:
314  {
315  rescale();
316  break;
317  }
318  default:;
319  }
320  }
321 
322  return false;
323 }
324 
331 void QwtPlotRescaler::canvasResizeEvent( QResizeEvent* event )
332 {
333  int left, top, right, bottom;
334  canvas()->getContentsMargins( &left, &top, &right, &bottom );
335 
336  const QSize marginSize( left + right, top + bottom );
337 
338  const QSize newSize = event->size() - marginSize;
339  const QSize oldSize = event->oldSize() - marginSize;
340 
341  rescale( oldSize, newSize );
342 }
343 
346 {
347  const QSize size = canvas()->contentsRect().size();
348  rescale( size, size );
349 }
350 
358  const QSize &oldSize, const QSize &newSize ) const
359 {
360  if ( newSize.isEmpty() )
361  return;
362 
363  QwtInterval intervals[QwtPlot::axisCnt];
364  for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
365  intervals[axis] = interval( axis );
366 
367  const int refAxis = referenceAxis();
368  intervals[refAxis] = expandScale( refAxis, oldSize, newSize );
369 
370  for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
371  {
372  if ( aspectRatio( axis ) > 0.0 && axis != refAxis )
373  intervals[axis] = syncScale( axis, intervals[refAxis], newSize );
374  }
375 
376  updateScales( intervals );
377 }
378 
389  const QSize &oldSize, const QSize &newSize ) const
390 {
391  const QwtInterval oldInterval = interval( axis );
392 
393  QwtInterval expanded = oldInterval;
394  switch ( rescalePolicy() )
395  {
396  case Fixed:
397  {
398  break; // do nothing
399  }
400  case Expanding:
401  {
402  if ( !oldSize.isEmpty() )
403  {
404  double width = oldInterval.width();
405  if ( orientation( axis ) == Qt::Horizontal )
406  width *= double( newSize.width() ) / oldSize.width();
407  else
408  width *= double( newSize.height() ) / oldSize.height();
409 
410  expanded = expandInterval( oldInterval,
411  width, expandingDirection( axis ) );
412  }
413  break;
414  }
415  case Fitting:
416  {
417  double dist = 0.0;
418  for ( int ax = 0; ax < QwtPlot::axisCnt; ax++ )
419  {
420  const double d = pixelDist( ax, newSize );
421  if ( d > dist )
422  dist = d;
423  }
424  if ( dist > 0.0 )
425  {
426  double width;
427  if ( orientation( axis ) == Qt::Horizontal )
428  width = newSize.width() * dist;
429  else
430  width = newSize.height() * dist;
431 
432  expanded = expandInterval( intervalHint( axis ),
433  width, expandingDirection( axis ) );
434  }
435  break;
436  }
437  }
438 
439  return expanded;
440 }
441 
452  const QwtInterval& reference, const QSize &size ) const
453 {
454  double dist;
455  if ( orientation( referenceAxis() ) == Qt::Horizontal )
456  dist = reference.width() / size.width();
457  else
458  dist = reference.width() / size.height();
459 
460  if ( orientation( axis ) == Qt::Horizontal )
461  dist *= size.width();
462  else
463  dist *= size.height();
464 
465  dist /= aspectRatio( axis );
466 
467  QwtInterval intv;
468  if ( rescalePolicy() == Fitting )
469  intv = intervalHint( axis );
470  else
471  intv = interval( axis );
472 
473  intv = expandInterval( intv, dist, expandingDirection( axis ) );
474 
475  return intv;
476 }
477 
482 Qt::Orientation QwtPlotRescaler::orientation( int axis ) const
483 {
484  if ( axis == QwtPlot::yLeft || axis == QwtPlot::yRight )
485  return Qt::Vertical;
486 
487  return Qt::Horizontal;
488 }
489 
495 {
496  if ( axis < 0 || axis >= QwtPlot::axisCnt )
497  return QwtInterval();
498 
499  return plot()->axisScaleDiv( axis ).interval().normalized();
500 }
501 
512  const QwtInterval &interval, double width,
513  ExpandingDirection direction ) const
514 {
515  QwtInterval expanded = interval;
516 
517  switch ( direction )
518  {
519  case ExpandUp:
520  expanded.setMinValue( interval.minValue() );
521  expanded.setMaxValue( interval.minValue() + width );
522  break;
523 
524  case ExpandDown:
525  expanded.setMaxValue( interval.maxValue() );
526  expanded.setMinValue( interval.maxValue() - width );
527  break;
528 
529  case ExpandBoth:
530  default:
531  expanded.setMinValue( interval.minValue() +
532  interval.width() / 2.0 - width / 2.0 );
533  expanded.setMaxValue( expanded.minValue() + width );
534  }
535  return expanded;
536 }
537 
538 double QwtPlotRescaler::pixelDist( int axis, const QSize &size ) const
539 {
540  const QwtInterval intv = intervalHint( axis );
541 
542  double dist = 0.0;
543  if ( !intv.isNull() )
544  {
545  if ( axis == referenceAxis() )
546  dist = intv.width();
547  else
548  {
549  const double r = aspectRatio( axis );
550  if ( r > 0.0 )
551  dist = intv.width() * r;
552  }
553  }
554 
555  if ( dist > 0.0 )
556  {
557  if ( orientation( axis ) == Qt::Horizontal )
558  dist /= size.width();
559  else
560  dist /= size.height();
561  }
562 
563  return dist;
564 }
565 
572  QwtInterval intervals[QwtPlot::axisCnt] ) const
573 {
574  if ( d_data->inReplot >= 5 )
575  {
576  return;
577  }
578 
579  QwtPlot *plt = const_cast<QwtPlot *>( plot() );
580 
581  const bool doReplot = plt->autoReplot();
582  plt->setAutoReplot( false );
583 
584  for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
585  {
586  if ( axis == referenceAxis() || aspectRatio( axis ) > 0.0 )
587  {
588  double v1 = intervals[axis].minValue();
589  double v2 = intervals[axis].maxValue();
590 
591  if ( !plt->axisScaleDiv( axis ).isIncreasing() )
592  qSwap( v1, v2 );
593 
594  if ( d_data->inReplot >= 1 )
595  d_data->axisData[axis].scaleDiv = plt->axisScaleDiv( axis );
596 
597  if ( d_data->inReplot >= 2 )
598  {
599  QList<double> ticks[QwtScaleDiv::NTickTypes];
600  for ( int i = 0; i < QwtScaleDiv::NTickTypes; i++ )
601  ticks[i] = d_data->axisData[axis].scaleDiv.ticks( i );
602 
603  plt->setAxisScaleDiv( axis, QwtScaleDiv( v1, v2, ticks ) );
604  }
605  else
606  {
607  plt->setAxisScale( axis, v1, v2 );
608  }
609  }
610  }
611 
612  QwtPlotCanvas *canvas = qobject_cast<QwtPlotCanvas *>( plt->canvas() );
613 
614  bool immediatePaint = false;
615  if ( canvas )
616  {
617  immediatePaint = canvas->testPaintAttribute( QwtPlotCanvas::ImmediatePaint );
619  }
620 
621  plt->setAutoReplot( doReplot );
622 
623  d_data->inReplot++;
624  plt->replot();
625  d_data->inReplot--;
626 
627  if ( canvas && immediatePaint )
628  {
630  }
631 }
d
const QwtScaleDiv & axisScaleDiv(int axisId) const
Return the scale division of a specified axis.
void setRescalePolicy(RescalePolicy)
QwtInterval normalized() const
Normalize the limits of the interval.
A class representing an interval.
Definition: qwt_interval.h:26
virtual void canvasResizeEvent(QResizeEvent *)
void setReferenceAxis(int axis)
Number of axes.
Definition: qwt_plot.h:108
QwtInterval interval(int axis) const
double minValue() const
Definition: qwt_interval.h:193
QwtInterval expandInterval(const QwtInterval &, double width, ExpandingDirection) const
void setAutoReplot(bool=true)
Set or reset the autoReplot option.
Definition: qwt_plot.cpp:314
Y axis right of the canvas.
Definition: qwt_plot.h:99
virtual void replot()
Redraw the plot.
Definition: qwt_plot.cpp:546
double aspectRatio(int axis) const
A class representing a scale division.
Definition: qwt_scale_div.h:36
Canvas of a QwtPlot.
A 2-D plotting widget.
Definition: qwt_plot.h:74
double maxValue() const
Definition: qwt_interval.h:199
bool testPaintAttribute(PaintAttribute) const
Y axis left of the canvas.
Definition: qwt_plot.h:96
int referenceAxis() const
virtual QwtInterval expandScale(int axis, const QSize &oldSize, const QSize &newSize) const
void setAxisScaleDiv(int axisId, const QwtScaleDiv &)
Disable autoscaling and specify a fixed scale for a selected axis.
QwtPlotRescaler::AxisData axisData[QwtPlot::axisCnt]
QwtPlotRescaler(QWidget *canvas, int referenceAxis=QwtPlot::xBottom, RescalePolicy=Expanding)
QwtInterval intervalHint(int axis) const
virtual bool eventFilter(QObject *, QEvent *)
Event filter for the plot canvas.
The lower limit of the scale is adjusted.
bool autoReplot
Definition: qwt_plot.h:80
void setExpandingDirection(ExpandingDirection)
PrivateData * d_data
void setEnabled(bool)
En/disable the rescaler.
bool isNull() const
Definition: qwt_interval.h:315
Both limits of the scale are adjusted.
virtual ~QwtPlotRescaler()
Destructor.
void rescale() const
Adjust the plot axes scales.
QwtPlotRescaler takes care of fixed aspect ratios for plot scales.
void setPaintAttribute(PaintAttribute, bool on=true)
Changing the paint attributes.
Number of valid tick types.
Definition: qwt_scale_div.h:55
ExpandingDirection expandingDirection(int axis) const
bool isIncreasing() const
Check if the scale division is increasing( lowerBound() <= upperBound() )
uintptr_t size
QwtPlotRescaler::ExpandingDirection expandingDirection
void setMinValue(double)
Definition: qwt_interval.h:177
TFSIMD_FORCE_INLINE const tfScalar & w() const
bool isEnabled() const
QWidget * canvas()
Definition: qwt_plot.cpp:467
Qt::Orientation orientation(int axis) const
The upper limit of the scale is adjusted.
void setAspectRatio(double ratio)
QwtInterval interval() const
virtual void updateScales(QwtInterval intervals[QwtPlot::axisCnt]) const
int i
double width() const
Return the width of an interval.
Definition: qwt_interval.h:228
QList< double > ticks(int tickType) const
double pixelDist(int axis, const QSize &) const
void setMaxValue(double)
Definition: qwt_interval.h:187
void setAxisScale(int axisId, double min, double max, double step=0)
Disable autoscaling and specify a fixed scale for a selected axis.
virtual QwtInterval syncScale(int axis, const QwtInterval &reference, const QSize &size) const
RescalePolicy rescalePolicy() const
void setIntervalHint(int axis, const QwtInterval &)


plotjuggler
Author(s): Davide Faconti
autogenerated on Sat Jul 6 2019 03:44:17