qwt_plot_multi_barchart.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 
11 #include "qwt_scale_map.h"
12 #include "qwt_column_symbol.h"
13 #include "qwt_text.h"
14 #include "qwt_graphic.h"
15 #include "qwt_legend_data.h"
16 #include "qwt_math.h"
17 
18 #include <qmap.h>
19 
20 inline static bool qwtIsIncreasing(
21  const QwtScaleMap &map, const QVector<double> &values )
22 {
23  bool isInverting = map.isInverting();
24 
25  for ( int i = 0; i < values.size(); i++ )
26  {
27  const double y = values[ i ];
28  if ( y != 0.0 )
29  return ( map.isInverting() != ( y > 0.0 ) );
30  }
31 
32  return !isInverting;
33 }
34 
36 {
37 public:
40  {
41  }
42 
46 };
47 
54 {
55  init();
56 }
57 
64 {
65  init();
66 }
67 
70 {
72  delete d_data;
73 }
74 
76 {
77  d_data = new PrivateData;
78  setData( new QwtSetSeriesData() );
79 }
80 
83 {
85 }
86 
92  const QVector<QwtSetSample> &samples )
93 {
94  setData( new QwtSetSeriesData( samples ) );
95 }
96 
102  const QVector< QVector<double> > &samples )
103 {
105  s.reserve( samples.size() );
106 
107  for ( int i = 0; i < samples.size(); i++ )
108  s += QwtSetSample( i, samples[ i ] );
109 
110  setData( new QwtSetSeriesData( s ) );
111 }
112 
125 {
126  setData( data );
127 }
128 
139 {
140  d_data->barTitles = titles;
141  itemChanged();
142 }
143 
149 {
150  return d_data->barTitles;
151 }
152 
165 {
166  if ( valueIndex < 0 )
167  return;
168 
170  d_data->symbolMap.find(valueIndex);
171  if ( it == d_data->symbolMap.end() )
172  {
173  if ( symbol != NULL )
174  {
175  d_data->symbolMap.insert( valueIndex, symbol );
176 
177  legendChanged();
178  itemChanged();
179  }
180  }
181  else
182  {
183  if ( symbol != it.value() )
184  {
185  delete it.value();
186 
187  if ( symbol == NULL )
188  {
189  d_data->symbolMap.remove( valueIndex );
190  }
191  else
192  {
193  it.value() = symbol;
194  }
195 
196  legendChanged();
197  itemChanged();
198  }
199  }
200 }
201 
210 const QwtColumnSymbol *QwtPlotMultiBarChart::symbol( int valueIndex ) const
211 {
213  d_data->symbolMap.constFind( valueIndex );
214 
215  return ( it == d_data->symbolMap.constEnd() ) ? NULL : it.value();
216 }
217 
227 {
229  d_data->symbolMap.constFind( valueIndex );
230 
231  return ( it == d_data->symbolMap.constEnd() ) ? NULL : it.value();
232 }
233 
238 {
239  qDeleteAll( d_data->symbolMap );
240  d_data->symbolMap.clear();
241 }
242 
264  int sampleIndex, int valueIndex ) const
265 {
266  Q_UNUSED( sampleIndex );
267  Q_UNUSED( valueIndex );
268 
269  return NULL;
270 }
271 
279 {
280  if ( style != d_data->style )
281  {
282  d_data->style = style;
283 
284  legendChanged();
285  itemChanged();
286  }
287 }
288 
294 {
295  return d_data->style;
296 }
297 
303 {
304  const size_t numSamples = dataSize();
305 
306  if ( numSamples == 0 )
308 
309  const double baseLine = baseline();
310 
311  QRectF rect;
312 
314  {
316 
317  if ( rect.height() >= 0 )
318  {
319  if ( rect.bottom() < baseLine )
320  rect.setBottom( baseLine );
321  if ( rect.top() > baseLine )
322  rect.setTop( baseLine );
323  }
324  }
325  else
326  {
327  double xMin, xMax, yMin, yMax;
328 
329  xMin = xMax = 0.0;
330  yMin = yMax = baseLine;
331 
332  const QwtSeriesData<QwtSetSample> *series = data();
333 
334  for ( size_t i = 0; i < numSamples; i++ )
335  {
336  const QwtSetSample sample = series->sample( i );
337  if ( i == 0 )
338  {
339  xMin = xMax = sample.value;
340  }
341  else
342  {
343  xMin = qwtMinF( xMin, sample.value );
344  xMax = qwtMaxF( xMax, sample.value );
345  }
346 
347  const double y = baseLine + sample.added();
348 
349  yMin = qwtMinF( yMin, y );
350  yMax = qwtMaxF( yMax, y );
351  }
352  rect.setRect( xMin, yMin, xMax - xMin, yMax - yMin );
353  }
354 
355  if ( orientation() == Qt::Horizontal )
356  rect.setRect( rect.y(), rect.x(), rect.height(), rect.width() );
357 
358  return rect;
359 }
360 
374 void QwtPlotMultiBarChart::drawSeries( QPainter *painter,
375  const QwtScaleMap &xMap, const QwtScaleMap &yMap,
376  const QRectF &canvasRect, int from, int to ) const
377 {
378  if ( to < 0 )
379  to = dataSize() - 1;
380 
381  if ( from < 0 )
382  from = 0;
383 
384  if ( from > to )
385  return;
386 
387 
388  const QRectF br = data()->boundingRect();
389  const QwtInterval interval( br.left(), br.right() );
390 
391  painter->save();
392 
393  for ( int i = from; i <= to; i++ )
394  {
395  drawSample( painter, xMap, yMap,
396  canvasRect, interval, i, sample( i ) );
397  }
398 
399  painter->restore();
400 }
401 
415 void QwtPlotMultiBarChart::drawSample( QPainter *painter,
416  const QwtScaleMap &xMap, const QwtScaleMap &yMap,
417  const QRectF &canvasRect, const QwtInterval &boundingInterval,
418  int index, const QwtSetSample& sample ) const
419 {
420  if ( sample.set.size() <= 0 )
421  return;
422 
423  double sampleW;
424 
425  if ( orientation() == Qt::Horizontal )
426  {
427  sampleW = sampleWidth( yMap, canvasRect.height(),
428  boundingInterval.width(), sample.value );
429  }
430  else
431  {
432  sampleW = sampleWidth( xMap, canvasRect.width(),
433  boundingInterval.width(), sample.value );
434  }
435 
436  if ( d_data->style == Stacked )
437  {
438  drawStackedBars( painter, xMap, yMap,
439  canvasRect, index, sampleW, sample );
440  }
441  else
442  {
443  drawGroupedBars( painter, xMap, yMap,
444  canvasRect, index, sampleW, sample );
445  }
446 }
447 
462  const QwtScaleMap &xMap, const QwtScaleMap &yMap,
463  const QRectF &canvasRect, int index, double sampleWidth,
464  const QwtSetSample& sample ) const
465 {
466  Q_UNUSED( canvasRect );
467 
468  const int numBars = sample.set.size();
469  if ( numBars == 0 )
470  return;
471 
472  if ( orientation() == Qt::Vertical )
473  {
474  const double barWidth = sampleWidth / numBars;
475 
476  const double y1 = yMap.transform( baseline() );
477  const double x0 = xMap.transform( sample.value ) - 0.5 * sampleWidth;
478 
479  for ( int i = 0; i < numBars; i++ )
480  {
481  const double x1 = x0 + i * barWidth;
482  const double x2 = x1 + barWidth;
483 
484  const double y2 = yMap.transform( sample.set[i] );
485 
486  QwtColumnRect barRect;
487  barRect.direction = ( y1 < y2 ) ?
489 
490  barRect.hInterval = QwtInterval( x1, x2 ).normalized();
491  if ( i != 0 )
493 
494  barRect.vInterval = QwtInterval( y1, y2 ).normalized();
495 
496  drawBar( painter, index, i, barRect );
497  }
498  }
499  else
500  {
501  const double barHeight = sampleWidth / numBars;
502 
503  const double x1 = xMap.transform( baseline() );
504  const double y0 = yMap.transform( sample.value ) - 0.5 * sampleWidth;
505 
506  for ( int i = 0; i < numBars; i++ )
507  {
508  double y1 = y0 + i * barHeight;
509  double y2 = y1 + barHeight;
510 
511  double x2 = xMap.transform( sample.set[i] );
512 
513  QwtColumnRect barRect;
514  barRect.direction = x1 < x2 ?
516 
517  barRect.hInterval = QwtInterval( x1, x2 ).normalized();
518 
519  barRect.vInterval = QwtInterval( y1, y2 );
520  if ( i != 0 )
522 
523  drawBar( painter, index, i, barRect );
524  }
525  }
526 }
527 
542  const QwtScaleMap &xMap, const QwtScaleMap &yMap,
543  const QRectF &canvasRect, int index,
544  double sampleWidth, const QwtSetSample& sample ) const
545 {
546  Q_UNUSED( canvasRect ); // clipping the bars ?
547 
548  const int numBars = sample.set.size();
549  if ( numBars == 0 )
550  return;
551 
553 
554  if ( orientation() == Qt::Vertical )
555  {
556  const double x1 = xMap.transform( sample.value ) - 0.5 * sampleWidth;
557  const double x2 = x1 + sampleWidth;
558 
559  const bool increasing = qwtIsIncreasing( yMap, sample.set );
560 
561  QwtColumnRect bar;
562  bar.direction = increasing ?
564 
565  bar.hInterval = QwtInterval( x1, x2 ).normalized();
566 
567  double sum = baseline();
568 
569  for ( int i = 0; i < numBars; i++ )
570  {
571  const double si = sample.set[ i ];
572  if ( si == 0.0 )
573  continue;
574 
575  const double y1 = yMap.transform( sum );
576  const double y2 = yMap.transform( sum + si );
577 
578  if ( ( y2 > y1 ) != increasing )
579  {
580  // stacked bars need to be in the same direction
581  continue;
582  }
583 
584  bar.vInterval = QwtInterval( y1, y2 ).normalized();
585  bar.vInterval.setBorderFlags( borderFlags );
586 
587  drawBar( painter, index, i, bar );
588 
589  sum += si;
590 
591  if ( increasing )
592  borderFlags = QwtInterval::ExcludeMinimum;
593  else
594  borderFlags = QwtInterval::ExcludeMaximum;
595  }
596  }
597  else
598  {
599  const double y1 = yMap.transform( sample.value ) - 0.5 * sampleWidth;
600  const double y2 = y1 + sampleWidth;
601 
602  const bool increasing = qwtIsIncreasing( xMap, sample.set );
603 
604  QwtColumnRect bar;
605  bar.direction = increasing ?
607  bar.vInterval = QwtInterval( y1, y2 ).normalized();
608 
609  double sum = baseline();
610 
611  for ( int i = 0; i < sample.set.size(); i++ )
612  {
613  const double si = sample.set[ i ];
614  if ( si == 0.0 )
615  continue;
616 
617  const double x1 = xMap.transform( sum );
618  const double x2 = xMap.transform( sum + si );
619 
620  if ( ( x2 > x1 ) != increasing )
621  {
622  // stacked bars need to be in the same direction
623  continue;
624  }
625 
626  bar.hInterval = QwtInterval( x1, x2 ).normalized();
627  bar.hInterval.setBorderFlags( borderFlags );
628 
629  drawBar( painter, index, i, bar );
630 
631  sum += si;
632 
633  if ( increasing )
634  borderFlags = QwtInterval::ExcludeMinimum;
635  else
636  borderFlags = QwtInterval::ExcludeMaximum;
637  }
638  }
639 }
640 
652 void QwtPlotMultiBarChart::drawBar( QPainter *painter,
653  int sampleIndex, int valueIndex, const QwtColumnRect &rect ) const
654 {
655  const QwtColumnSymbol *specialSym = NULL;
656  if ( sampleIndex >= 0 )
657  specialSym = specialSymbol( sampleIndex, valueIndex );
658 
659  const QwtColumnSymbol *sym = specialSym;
660  if ( sym == NULL )
661  sym = symbol( valueIndex );
662 
663  if ( sym )
664  {
665  sym->draw( painter, rect );
666  }
667  else
668  {
669  // we build a temporary default symbol
670  QwtColumnSymbol columnSymbol( QwtColumnSymbol::Box );
671  columnSymbol.setLineWidth( 1 );
672  columnSymbol.setFrameStyle( QwtColumnSymbol::Plain );
673  columnSymbol.draw( painter, rect );
674  }
675 
676  delete specialSym;
677 }
678 
688 {
690  list.reserve( d_data->barTitles.size() );
691 
692  for ( int i = 0; i < d_data->barTitles.size(); i++ )
693  {
695 
697  QVariant::fromValue( d_data->barTitles[i] ) );
698 
699  if ( !legendIconSize().isEmpty() )
700  {
702  QVariant::fromValue( legendIcon( i, legendIconSize() ) ) );
703  }
704 
705  list += data;
706  }
707 
708  return list;
709 }
710 
721  const QSizeF &size ) const
722 {
723  QwtColumnRect column;
724  column.hInterval = QwtInterval( 0.0, size.width() - 1.0 );
725  column.vInterval = QwtInterval( 0.0, size.height() - 1.0 );
726 
727  QwtGraphic icon;
728  icon.setDefaultSize( size );
729  icon.setRenderHint( QwtGraphic::RenderPensUnscaled, true );
730 
731  QPainter painter( &icon );
732  painter.setRenderHint( QPainter::Antialiasing,
734 
735  drawBar( &painter, -1, index, column );
736 
737  return icon;
738 }
739 
virtual void legendChanged()
const QwtColumnSymbol * symbol(int valueIndex) const
QMap< int, QwtColumnSymbol * > symbolMap
Qt::Orientation orientation() const
QwtInterval vInterval
Interval for the vertical coordinates.
QwtInterval normalized() const
Normalize the limits of the interval.
Enable antialiasing.
virtual QwtGraphic legendIcon(int index, const QSizeF &) const QWT_OVERRIDE
A plain frame style.
double value
value
Definition: qwt_samples.h:89
Interface for iterating over an array of samples.
virtual QRectF boundingRect() const =0
From top to bottom.
A class representing an interval.
Definition: qwt_interval.h:22
Max value is not included in the interval.
Definition: qwt_interval.h:38
QWT_CONSTEXPR float qwtMaxF(float a, float b)
Definition: qwt_math.h:123
virtual void drawSeries(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int from, int to) const QWT_OVERRIDE
From left to right.
A drawing primitive for columns.
void drawStackedBars(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int index, double sampleWidth, const QwtSetSample &) const
For QwtPlotMultiBarChart.
virtual int rtti() const QWT_OVERRIDE
void setData(QwtSeriesData< QwtSetSample > *series)
QwtPlotMultiBarChart displays a series of a samples that consist each of a set of values...
Direction direction
Direction.
virtual void drawBar(QPainter *, int sampleIndex, int valueIndex, const QwtColumnRect &) const
static bool qwtIsIncreasing(const QwtScaleMap &map, const QVector< double > &values)
Abstract base class for bar chart items.
QwtSeriesData< QwtSetSample > * data()
QWT_CONSTEXPR float qwtMinF(float a, float b)
Definition: qwt_math.h:99
virtual QRectF boundingRect() const QWT_OVERRIDE
void setStyle(ChartStyle style)
void setBarTitles(const QList< QwtText > &)
Set the titles for the bars.
void setSamples(const QVector< QwtSetSample > &)
QSize legendIconSize() const
A sample of the types (x1...xn, y) or (x, y1..yn)
Definition: qwt_samples.h:77
void setDefaultSize(const QSizeF &)
Set a default size.
virtual QList< QwtLegendData > legendData() const QWT_OVERRIDE
QList< QwtText > barTitles() const
void setSymbol(int valueIndex, QwtColumnSymbol *)
Add a symbol to the symbol map.
double added() const
Definition: qwt_samples.h:129
bool testRenderHint(RenderHint) const
double sampleWidth(const QwtScaleMap &map, double canvasSize, double boundingSize, double value) const
QwtPlotMultiBarChart::ChartStyle style
virtual QwtColumnSymbol * specialSymbol(int sampleIndex, int valueIndex) const
Create a symbol for special values.
A class representing a text.
Definition: qwt_text.h:51
Min value is not included in the interval.
Definition: qwt_interval.h:35
void setFrameStyle(FrameStyle)
A paint device for scalable graphics.
Definition: qwt_graphic.h:75
virtual void drawSample(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, const QwtInterval &boundingInterval, int index, const QwtSetSample &) const
From bottom to top.
void setBorderFlags(BorderFlags)
Definition: qwt_interval.h:155
void setLineWidth(int width)
A scale map.
Definition: qwt_scale_map.h:26
QwtSetSample sample(int index) const
virtual void itemChanged()
virtual ~QwtPlotMultiBarChart()
Destructor.
void drawGroupedBars(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, int index, double sampleWidth, const QwtSetSample &) const
QwtPlotMultiBarChart(const QString &title=QString())
Directed rectangle representing bounding rectangle and orientation of a column.
void setValue(int role, const QVariant &)
virtual void draw(QPainter *, const QwtColumnRect &) const
QwtInterval hInterval
Interval for the horizontal coordinates.
virtual T sample(size_t i) const =0
The bars of a set are displayed side by side.
virtual size_t dataSize() const QWT_OVERRIDE
bool isInverting() const
double transform(double s) const
From right to left.
double width() const
Return the width of an interval.
Definition: qwt_interval.h:225
Min/Max values are inside the interval.
Definition: qwt_interval.h:32
QVector< double > set
Vector of values associated to value.
Definition: qwt_samples.h:92
Attributes of an entry on a legend.
virtual QRectF boundingRect() const QWT_OVERRIDE
const QwtText & title() const


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:48:10