Developer Documentation
QwtHistogramm.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 
51 // Include the plot header to get the qwt version
52 #include <qwt_plot.h>
53 
54 // This file is for QWT >= 6.0 only
55 #if QWT_VERSION >= 0x060000
56 
57 #include <qwt_plot_histogram.h>
58 #include <qwt_painter.h>
59 #include <qwt_scale_map.h>
60 
61 #include <QString>
62 #include <QPainter>
63 
64 #include <iostream>
65 
66 
67 #include "QwtHistogramm.hh"
68 
69 class Histogram::PrivateData {
70 
71 public:
72 
73  PrivateData() :
74  attributes(Histogram::Auto),
75  data(0),
76  reference(0.0)
77  {}
78 
79  int attributes;
80  QwtIntervalSeriesData* data;
81  std::vector<QColor> colors_;
82  double reference;
83 
84 };
85 
86 Histogram::Histogram(const QwtText &title) :
87  QwtPlotItem(title)
88 {
89  init();
90 }
91 
92 Histogram::Histogram(const QString &title) :
93  QwtPlotItem(QwtText(title))
94 {
95  init();
96 }
97 
99 {
100  delete d_data;
101 }
102 
103 void Histogram::init()
104 {
105  d_data = new PrivateData();
106 
107  setItemAttribute(QwtPlotItem::AutoScale, true);
108  setItemAttribute(QwtPlotItem::Legend, true);
109 
110  setZ(20.0);
111 }
112 
113 void Histogram::setBaseline(double reference)
114 {
115  if (d_data->reference != reference) {
116  d_data->reference = reference;
117  itemChanged();
118  }
119 }
120 
121 double Histogram::baseline() const
122 {
123  return d_data->reference;
124 }
125 
126 void Histogram::setData(QwtIntervalSeriesData* data)
127 {
128  d_data->data = data;
129  itemChanged();
130 }
131 
132 const QwtIntervalSeriesData* Histogram::data() const
133 {
134  return d_data->data;
135 }
136 
137 void Histogram::setColors(std::vector<QColor>& _colors)
138 {
139  d_data->colors_ = _colors;
140  itemChanged();
141 }
142 
143 QColor Histogram::color(uint i) const
144 {
145  if (i < d_data->colors_.size())
146  return d_data->colors_[i];
147  else
148  return Qt::darkBlue;
149 }
150 
151 QRectF Histogram::boundingRect() const
152 {
153  QRectF rect = d_data->data->boundingRect();
154  if (!rect.isValid())
155  return rect;
156 
157  if (d_data->attributes & Xfy) {
158  rect = QRectF(rect.y(), rect.x(), rect.height(), rect.width());
159 
160  if (rect.left() > d_data->reference)
161  rect.setLeft(d_data->reference);
162  else if (rect.right() < d_data->reference)
163  rect.setRight(d_data->reference);
164  } else {
165  if (rect.bottom() < d_data->reference)
166  rect.setBottom(d_data->reference);
167  else if (rect.top() > d_data->reference)
168  rect.setTop(d_data->reference);
169  }
170 
171  return rect;
172 }
173 
174 
175 int Histogram::rtti() const
176 {
177  return QwtPlotItem::Rtti_PlotHistogram;
178 }
179 
180 void Histogram::setHistogramAttribute(HistogramAttribute attribute, bool on)
181 {
182  if (bool(d_data->attributes & attribute) == on)
183  return;
184 
185  if (on)
186  d_data->attributes |= attribute;
187  else
188  d_data->attributes &= ~attribute;
189 
190  itemChanged();
191 }
192 
193 bool Histogram::testHistogramAttribute(HistogramAttribute attribute) const
194 {
195  return d_data->attributes & attribute;
196 }
197 
198 void Histogram::draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &) const
199 {
200  const QwtIntervalSeriesData &iData = *(d_data->data);
201 
202  const int x0 = xMap.transform(baseline());
203  const int y0 = yMap.transform(baseline());
204 
205  for (int i = 0; i < (int) iData.size(); i++) {
206  if (d_data->attributes & Histogram::Xfy) {
207  const int x2 = xMap.transform(iData.sample(i).value);
208  if (x2 == x0)
209  continue;
210 
211  int y1 = yMap.transform(iData.sample(i).interval.minValue());
212  int y2 = yMap.transform(iData.sample(i).interval.maxValue());
213  if (y1 > y2)
214  qSwap(y1, y2);
215 
216  if (i < (int) iData.size() - 2) {
217  const int yy1 = yMap.transform(iData.sample(i + 1).interval.minValue());
218  const int yy2 = yMap.transform(iData.sample(i + 1).interval.maxValue());
219 
220  if (y2 == qMin(yy1, yy2)) {
221  const int xx2 = xMap.transform(iData.sample(i + 1).interval.minValue());
222  if (xx2 != x0 && ((xx2 < x0 && x2 < x0) || (xx2 > x0 && x2 > x0))) {
223  // One pixel distance between neighbored bars
224  y2++;
225  }
226  }
227  }
228 
229  painter->setPen(QPen(color(i)));
230 
231  drawBar(painter, Qt::Horizontal, QRect(x0, y1, x2 - x0, y2 - y1));
232  } else {
233  const int y2 = yMap.transform(iData.sample(i).value);
234  if (y2 == y0)
235  continue;
236 
237  int x1 = xMap.transform(iData.sample(i).interval.minValue());
238  int x2 = xMap.transform(iData.sample(i).interval.maxValue());
239  if (x1 > x2)
240  qSwap(x1, x2);
241 
242  if (i < (int) iData.size() - 2) {
243  const int xx1 = xMap.transform(iData.sample(i + 1).interval.minValue());
244  const int xx2 = xMap.transform(iData.sample(i + 1).interval.maxValue());
245 
246  if (x2 == qMin(xx1, xx2)) {
247  const int yy2 = yMap.transform(iData.sample(i + 1).value);
248  if (yy2 != y0 && ((yy2 < y0 && y2 < y0) || (yy2 > y0 && y2 > y0))) {
249  // One pixel distance between neighbored bars
250  x2--;
251  }
252  }
253  }
254 
255  painter->setPen(QPen(color(i)));
256 
257  drawBar(painter, Qt::Vertical, QRect(x1, y0, x2 - x1, y2 - y0));
258  }
259  }
260 }
261 
262 void Histogram::drawBar(QPainter *painter, Qt::Orientation, const QRect& rect) const
263 {
264  painter->save();
265 
266  const QColor color(painter->pen().color());
267  const QRect r = rect.normalized();
268 
269  const int factor = 125;
270  const QColor light(color.light(factor));
271  const QColor dark(color.dark(factor));
272 
273  painter->setBrush(color);
274  painter->setPen(Qt::NoPen);
275  QwtPainter::drawRect(painter, r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2);
276  painter->setBrush(Qt::NoBrush);
277 
278  painter->setPen(QPen(light, 2));
279 
280  QwtPainter::drawLine(painter, r.left() + 1, r.top() + 2, r.right() + 1, r.top() + 2);
281 
282  painter->setPen(QPen(dark, 2));
283 
284  painter->setPen(QPen(light, 1));
285 
286  QwtPainter::drawLine(painter, r.left(), r.top() + 1, r.left(), r.bottom());
287  QwtPainter::drawLine(painter, r.left() + 1, r.top() + 2, r.left() + 1, r.bottom() - 1);
288 
289  painter->setPen(QPen(dark, 1));
290 
291  QwtPainter::drawLine(painter, r.right() + 1, r.top() + 1, r.right() + 1, r.bottom());
292  QwtPainter::drawLine(painter, r.right(), r.top() + 2, r.right(), r.bottom() - 1);
293 
294  painter->restore();
295 }
296 
297 #endif
virtual void draw(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &) const
The actual draw function, drawing the bars inside the plot widget.
virtual QRectF boundingRect() const
Function hat will return the datas bounding rectangle (for rendering)
void setColors(std::vector< QColor > &_colors)
Set colors.
virtual ~Histogram()
Destructor.
Histogram(const QString &title=QString::null)
Constructor.
virtual void drawBar(QPainter *, Qt::Orientation o, const QRect &) const
Draws a single bar.
Histogram plot.
void setData(QwtIntervalSeriesData *data)
set data to render