qwt_plot_histogram.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_histogram.h"
11 #include "qwt_plot.h"
12 #include "qwt_painter.h"
13 #include "qwt_column_symbol.h"
14 #include "qwt_scale_map.h"
15 #include <qstring.h>
16 #include <qpainter.h>
17 
18 static inline bool qwtIsCombinable( const QwtInterval &d1,
19  const QwtInterval &d2 )
20 {
21  if ( d1.isValid() && d2.isValid() )
22  {
23  if ( d1.maxValue() == d2.minValue() )
24  {
27  {
28  return true;
29  }
30  }
31  }
32 
33  return false;
34 }
35 
37 {
38 public:
40  baseline( 0.0 ),
41  style( Columns ),
42  symbol( NULL )
43  {
44  }
45 
47  {
48  delete symbol;
49  }
50 
51  double baseline;
52 
53  QPen pen;
54  QBrush brush;
57 };
58 
64  QwtPlotSeriesItem( title )
65 {
66  init();
67 }
68 
74  QwtPlotSeriesItem( title )
75 {
76  init();
77 }
78 
81 {
82  delete d_data;
83 }
84 
87 {
88  d_data = new PrivateData();
90 
93 
94  setZ( 20.0 );
95 }
96 
104 {
105  if ( style != d_data->style )
106  {
107  d_data->style = style;
108 
109  legendChanged();
110  itemChanged();
111  }
112 }
113 
119 {
120  return d_data->style;
121 }
122 
136 void QwtPlotHistogram::setPen( const QColor &color, qreal width, Qt::PenStyle style )
137 {
138  setPen( QPen( color, width, style ) );
139 }
140 
147 void QwtPlotHistogram::setPen( const QPen &pen )
148 {
149  if ( pen != d_data->pen )
150  {
151  d_data->pen = pen;
152 
153  legendChanged();
154  itemChanged();
155  }
156 }
157 
162 const QPen &QwtPlotHistogram::pen() const
163 {
164  return d_data->pen;
165 }
166 
173 void QwtPlotHistogram::setBrush( const QBrush &brush )
174 {
175  if ( brush != d_data->brush )
176  {
177  d_data->brush = brush;
178 
179  legendChanged();
180  itemChanged();
181  }
182 }
183 
188 const QBrush &QwtPlotHistogram::brush() const
189 {
190  return d_data->brush;
191 }
192 
208 {
209  if ( symbol != d_data->symbol )
210  {
211  delete d_data->symbol;
212  d_data->symbol = symbol;
213 
214  legendChanged();
215  itemChanged();
216  }
217 }
218 
224 {
225  return d_data->symbol;
226 }
227 
239 void QwtPlotHistogram::setBaseline( double value )
240 {
241  if ( d_data->baseline != value )
242  {
243  d_data->baseline = value;
244  itemChanged();
245  }
246 }
247 
253 {
254  return d_data->baseline;
255 }
256 
262 {
263  QRectF rect = data()->boundingRect();
264  if ( !rect.isValid() )
265  return rect;
266 
267  if ( orientation() == Qt::Horizontal )
268  {
269  rect = QRectF( rect.y(), rect.x(),
270  rect.height(), rect.width() );
271 
272  if ( rect.left() > d_data->baseline )
273  rect.setLeft( d_data->baseline );
274  else if ( rect.right() < d_data->baseline )
275  rect.setRight( d_data->baseline );
276  }
277  else
278  {
279  if ( rect.bottom() < d_data->baseline )
280  rect.setBottom( d_data->baseline );
281  else if ( rect.top() > d_data->baseline )
282  rect.setTop( d_data->baseline );
283  }
284 
285  return rect;
286 }
287 
290 {
292 }
293 
299  const QVector<QwtIntervalSample> &samples )
300 {
301  setData( new QwtIntervalSeriesData( samples ) );
302 }
303 
316 {
317  setData( data );
318 }
319 
333 void QwtPlotHistogram::drawSeries( QPainter *painter,
334  const QwtScaleMap &xMap, const QwtScaleMap &yMap,
335  const QRectF &, int from, int to ) const
336 {
337  if ( !painter || dataSize() <= 0 )
338  return;
339 
340  if ( to < 0 )
341  to = dataSize() - 1;
342 
343  switch ( d_data->style )
344  {
345  case Outline:
346  drawOutline( painter, xMap, yMap, from, to );
347  break;
348  case Lines:
349  drawLines( painter, xMap, yMap, from, to );
350  break;
351  case Columns:
352  drawColumns( painter, xMap, yMap, from, to );
353  break;
354  default:
355  break;
356  }
357 }
358 
373 void QwtPlotHistogram::drawOutline( QPainter *painter,
374  const QwtScaleMap &xMap, const QwtScaleMap &yMap,
375  int from, int to ) const
376 {
377  const bool doAlign = QwtPainter::roundingAlignment( painter );
378 
379  double v0 = ( orientation() == Qt::Horizontal ) ?
380  xMap.transform( baseline() ) : yMap.transform( baseline() );
381  if ( doAlign )
382  v0 = qRound( v0 );
383 
384  QwtIntervalSample previous;
385 
386  QPolygonF polygon;
387  for ( int i = from; i <= to; i++ )
388  {
389  const QwtIntervalSample sample = this->sample( i );
390 
391  if ( !sample.interval.isValid() )
392  {
393  flushPolygon( painter, v0, polygon );
394  previous = sample;
395  continue;
396  }
397 
398  if ( previous.interval.isValid() )
399  {
400  if ( !qwtIsCombinable( previous.interval, sample.interval ) )
401  flushPolygon( painter, v0, polygon );
402  }
403 
404  if ( orientation() == Qt::Vertical )
405  {
406  double x1 = xMap.transform( sample.interval.minValue() );
407  double x2 = xMap.transform( sample.interval.maxValue() );
408  double y = yMap.transform( sample.value );
409  if ( doAlign )
410  {
411  x1 = qRound( x1 );
412  x2 = qRound( x2 );
413  y = qRound( y );
414  }
415 
416  if ( polygon.size() == 0 )
417  polygon += QPointF( x1, v0 );
418 
419  polygon += QPointF( x1, y );
420  polygon += QPointF( x2, y );
421  }
422  else
423  {
424  double y1 = yMap.transform( sample.interval.minValue() );
425  double y2 = yMap.transform( sample.interval.maxValue() );
426  double x = xMap.transform( sample.value );
427  if ( doAlign )
428  {
429  y1 = qRound( y1 );
430  y2 = qRound( y2 );
431  x = qRound( x );
432  }
433 
434  if ( polygon.size() == 0 )
435  polygon += QPointF( v0, y1 );
436 
437  polygon += QPointF( x, y1 );
438  polygon += QPointF( x, y2 );
439  }
440  previous = sample;
441  }
442 
443  flushPolygon( painter, v0, polygon );
444 }
445 
458 void QwtPlotHistogram::drawColumns( QPainter *painter,
459  const QwtScaleMap &xMap, const QwtScaleMap &yMap,
460  int from, int to ) const
461 {
462  painter->setPen( d_data->pen );
463  painter->setBrush( d_data->brush );
464 
465  const QwtSeriesData<QwtIntervalSample> *series = data();
466 
467  for ( int i = from; i <= to; i++ )
468  {
469  const QwtIntervalSample sample = series->sample( i );
470  if ( !sample.interval.isNull() )
471  {
472  const QwtColumnRect rect = columnRect( sample, xMap, yMap );
473  drawColumn( painter, rect, sample );
474  }
475  }
476 }
477 
490 void QwtPlotHistogram::drawLines( QPainter *painter,
491  const QwtScaleMap &xMap, const QwtScaleMap &yMap,
492  int from, int to ) const
493 {
494  const bool doAlign = QwtPainter::roundingAlignment( painter );
495 
496  painter->setPen( d_data->pen );
497  painter->setBrush( Qt::NoBrush );
498 
499  const QwtSeriesData<QwtIntervalSample> *series = data();
500 
501  for ( int i = from; i <= to; i++ )
502  {
503  const QwtIntervalSample sample = series->sample( i );
504  if ( !sample.interval.isNull() )
505  {
506  const QwtColumnRect rect = columnRect( sample, xMap, yMap );
507 
508  QRectF r = rect.toRect();
509  if ( doAlign )
510  {
511  r.setLeft( qRound( r.left() ) );
512  r.setRight( qRound( r.right() ) );
513  r.setTop( qRound( r.top() ) );
514  r.setBottom( qRound( r.bottom() ) );
515  }
516 
517  switch ( rect.direction )
518  {
520  {
521  QwtPainter::drawLine( painter,
522  r.topRight(), r.bottomRight() );
523  break;
524  }
526  {
527  QwtPainter::drawLine( painter,
528  r.topLeft(), r.bottomLeft() );
529  break;
530  }
532  {
533  QwtPainter::drawLine( painter,
534  r.bottomRight(), r.bottomLeft() );
535  break;
536  }
538  {
539  QwtPainter::drawLine( painter,
540  r.topRight(), r.topLeft() );
541  break;
542  }
543  }
544  }
545  }
546 }
547 
549 void QwtPlotHistogram::flushPolygon( QPainter *painter,
550  double baseLine, QPolygonF &polygon ) const
551 {
552  if ( polygon.size() == 0 )
553  return;
554 
555  if ( orientation() == Qt::Horizontal )
556  polygon += QPointF( baseLine, polygon.last().y() );
557  else
558  polygon += QPointF( polygon.last().x(), baseLine );
559 
560  if ( d_data->brush.style() != Qt::NoBrush )
561  {
562  painter->setPen( Qt::NoPen );
563  painter->setBrush( d_data->brush );
564 
565  if ( orientation() == Qt::Horizontal )
566  {
567  polygon += QPointF( polygon.last().x(), baseLine );
568  polygon += QPointF( polygon.first().x(), baseLine );
569  }
570  else
571  {
572  polygon += QPointF( baseLine, polygon.last().y() );
573  polygon += QPointF( baseLine, polygon.first().y() );
574  }
575 
576  QwtPainter::drawPolygon( painter, polygon );
577 
578  polygon.pop_back();
579  polygon.pop_back();
580  }
581  if ( d_data->pen.style() != Qt::NoPen )
582  {
583  painter->setBrush( Qt::NoBrush );
584  painter->setPen( d_data->pen );
585  QwtPainter::drawPolyline( painter, polygon );
586  }
587  polygon.clear();
588 }
589 
600  const QwtScaleMap &xMap, const QwtScaleMap &yMap ) const
601 {
602  QwtColumnRect rect;
603 
604  const QwtInterval &iv = sample.interval;
605  if ( !iv.isValid() )
606  return rect;
607 
608  if ( orientation() == Qt::Horizontal )
609  {
610  const double x0 = xMap.transform( baseline() );
611  const double x = xMap.transform( sample.value );
612  const double y1 = yMap.transform( iv.minValue() );
613  const double y2 = yMap.transform( iv.maxValue() );
614 
615  rect.hInterval.setInterval( x0, x );
616  rect.vInterval.setInterval( y1, y2, iv.borderFlags() );
617  rect.direction = ( x < x0 ) ? QwtColumnRect::RightToLeft :
619  }
620  else
621  {
622  const double x1 = xMap.transform( iv.minValue() );
623  const double x2 = xMap.transform( iv.maxValue() );
624  const double y0 = yMap.transform( baseline() );
625  const double y = yMap.transform( sample.value );
626 
627  rect.hInterval.setInterval( x1, x2, iv.borderFlags() );
628  rect.vInterval.setInterval( y0, y );
629  rect.direction = ( y < y0 ) ? QwtColumnRect::BottomToTop :
631  }
632 
633  return rect;
634 }
635 
650 void QwtPlotHistogram::drawColumn( QPainter *painter,
651  const QwtColumnRect &rect, const QwtIntervalSample &sample ) const
652 {
653  Q_UNUSED( sample );
654 
655  if ( d_data->symbol &&
657  {
658  d_data->symbol->draw( painter, rect );
659  }
660  else
661  {
662  QRectF r = rect.toRect();
663  if ( QwtPainter::roundingAlignment( painter ) )
664  {
665  r.setLeft( qRound( r.left() ) );
666  r.setRight( qRound( r.right() ) );
667  r.setTop( qRound( r.top() ) );
668  r.setBottom( qRound( r.bottom() ) );
669  }
670 
671  QwtPainter::drawRect( painter, r );
672  }
673 }
674 
686  const QSizeF &size ) const
687 {
688  Q_UNUSED( index );
689  return defaultIcon( d_data->brush, size );
690 }
static bool qwtIsCombinable(const QwtInterval &d1, const QwtInterval &d2)
virtual void legendChanged()
virtual size_t dataSize() const
Qt::Orientation orientation() const
Style style() const
QwtInterval vInterval
Interval for the vertical coordinates.
static void drawLine(QPainter *, double x1, double y1, double x2, double y2)
Wrapper for QPainter::drawLine()
Definition: qwt_painter.h:147
void setStyle(HistogramStyle style)
PrivateData * d_data
virtual QRectF boundingRect() const =0
From top to bottom.
A class representing an interval.
Definition: qwt_interval.h:26
void setPen(const QColor &, qreal width=0.0, Qt::PenStyle=Qt::SolidLine)
Max value is not included in the interval.
Definition: qwt_interval.h:42
virtual void drawColumn(QPainter *, const QwtColumnRect &, const QwtIntervalSample &) const
double minValue() const
Definition: qwt_interval.h:193
QRectF toRect() const
virtual QwtGraphic legendIcon(int index, const QSizeF &) const
From left to right.
A drawing primitive for columns.
void drawLines(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
void setData(QwtSeriesData< QwtIntervalSample > *series)
const QwtColumnSymbol * symbol
Direction direction
Direction.
void setSamples(const QVector< QwtIntervalSample > &)
virtual ~QwtPlotHistogram()
Destructor.
QwtSeriesData< QwtIntervalSample > * data()
QwtGraphic defaultIcon(const QBrush &, const QSizeF &) const
Return a default icon from a brush.
TFSIMD_FORCE_INLINE const tfScalar & y() const
double maxValue() const
Definition: qwt_interval.h:199
No Style, the symbol draws nothing.
For QwtPlotHistogram.
void drawColumns(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
HistogramStyle style() const
void init()
Initialize data members.
The item is represented on the legend.
const QwtColumnSymbol * symbol() const
static void drawPolygon(QPainter *, const QPolygonF &)
Wrapper for QPainter::drawPolygon()
void setInterval(double minValue, double maxValue, BorderFlags=IncludeBorders)
Definition: qwt_interval.h:144
static void drawRect(QPainter *, double x, double y, double w, double h)
Wrapper for QPainter::drawRect()
A sample of the types (x1-x2, y) or (x, y1-y2)
Definition: qwt_samples.h:19
void setBaseline(double reference)
Set the value of the baseline.
virtual int rtti() const
bool isValid() const
Definition: qwt_interval.h:211
A class representing a text.
Definition: qwt_text.h:51
void setZ(double z)
Set the z value.
bool isNull() const
Definition: qwt_interval.h:315
Min value is not included in the interval.
Definition: qwt_interval.h:39
A paint device for scalable graphics.
Definition: qwt_graphic.h:74
QwtPlotHistogram::HistogramStyle style
TFSIMD_FORCE_INLINE const tfScalar & x() const
From bottom to top.
virtual QRectF boundingRect() const
A scale map.
Definition: qwt_scale_map.h:30
BorderFlags borderFlags() const
Definition: qwt_interval.h:167
QwtIntervalSample sample(int index) const
virtual void itemChanged()
QwtPlotHistogram(const QString &title=QString())
void setBrush(const QBrush &)
Interface for iterating over an array of intervals.
static void drawPolyline(QPainter *, const QPolygonF &)
Wrapper for QPainter::drawPolyline()
void drawOutline(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, int from, int to) const
Directed rectangle representing bounding rectangle and orientation of a column.
virtual void draw(QPainter *, const QwtColumnRect &) const
virtual QwtColumnRect columnRect(const QwtIntervalSample &, const QwtScaleMap &, const QwtScaleMap &) const
QwtInterval hInterval
Interval for the horizontal coordinates.
virtual T sample(size_t i) const =0
const QBrush & brush() const
double value
Value.
Definition: qwt_samples.h:30
Base class for plot items representing a series of samples.
void setItemAttribute(ItemAttribute, bool on=true)
double transform(double s) const
void setSymbol(const QwtColumnSymbol *)
Assign a symbol.
int i
From right to left.
const QPen & pen() const
void flushPolygon(QPainter *, double baseLine, QPolygonF &) const
Internal, used by the Outline style.
double baseline() const
static bool roundingAlignment()
Definition: qwt_painter.h:176
virtual void drawSeries(QPainter *p, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to) const
const QwtText & title() const
QwtInterval interval
Interval.
Definition: qwt_samples.h:33


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