Developer Documentation
HistogramItem.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 
45 #ifdef WITH_QWT
46 
47 #include <qwt_plot.h>
48 
49 #if QWT_VERSION < 0x060000
50 #include <qstring.h>
51 #include <qpainter.h>
52 
53 #include <qwt_interval_data.h>
54 #include <qwt_painter.h>
55 #include <qwt_scale_map.h>
56 #include "HistogramItem.hh"
57 
58 class HistogramItem::PrivateData
59 {
60 public:
61  int attributes;
62  QwtIntervalData data;
63  std::vector< QColor > colors_;
64  double reference;
65 };
66 
67 HistogramItem::HistogramItem(const QwtText &title):
68  QwtPlotItem(title)
69 {
70  init();
71 }
72 
73 HistogramItem::HistogramItem(const QString &title):
74  QwtPlotItem(QwtText(title))
75 {
76  init();
77 }
78 
80 {
81  delete d_data;
82 }
83 
84 void HistogramItem::init()
85 {
86  d_data = new PrivateData();
87  d_data->reference = 0.0;
88  d_data->attributes = HistogramItem::Auto;
89 
90  setItemAttribute(QwtPlotItem::AutoScale, true);
91  setItemAttribute(QwtPlotItem::Legend, true);
92 
93  setZ(20.0);
94 }
95 
96 void HistogramItem::setBaseline(double reference)
97 {
98  if ( d_data->reference != reference )
99  {
100  d_data->reference = reference;
101  itemChanged();
102  }
103 }
104 
105 double HistogramItem::baseline() const
106 {
107  return d_data->reference;
108 }
109 
110 void HistogramItem::setData(const QwtIntervalData &data)
111 {
112  d_data->data = data;
113  itemChanged();
114 }
115 
116 const QwtIntervalData &HistogramItem::data() const
117 {
118  return d_data->data;
119 }
120 
121 void HistogramItem::setColors( std::vector< QColor >& _colors)
122 {
123  d_data->colors_ = _colors;
124  itemChanged();
125 }
126 
127 QColor HistogramItem::color(uint i) const
128 {
129  if ( i < d_data->colors_.size() )
130  return d_data->colors_[i];
131  else
132  return Qt::darkBlue;
133 }
134 
135 QwtDoubleRect HistogramItem::boundingRect() const
136 {
137  QwtDoubleRect rect = d_data->data.boundingRect();
138  if ( !rect.isValid() )
139  return rect;
140 
141  if ( d_data->attributes & Xfy )
142  {
143  rect = QwtDoubleRect( rect.y(), rect.x(), rect.height(), rect.width() );
144 
145  if ( rect.left() > d_data->reference )
146  rect.setLeft( d_data->reference );
147  else if ( rect.right() < d_data->reference )
148  rect.setRight( d_data->reference );
149  }
150  else
151  {
152  if ( rect.bottom() < d_data->reference )
153  rect.setBottom( d_data->reference );
154  else if ( rect.top() > d_data->reference )
155  rect.setTop( d_data->reference );
156  }
157 
158  return rect;
159 }
160 
161 
162 int HistogramItem::rtti() const
163 {
164  return QwtPlotItem::Rtti_PlotHistogram;
165 }
166 
167 void HistogramItem::setHistogramAttribute(HistogramAttribute attribute, bool on)
168 {
169  if ( bool(d_data->attributes & attribute) == on )
170  return;
171 
172  if ( on )
173  d_data->attributes |= attribute;
174  else
175  d_data->attributes &= ~attribute;
176 
177  itemChanged();
178 }
179 
180 bool HistogramItem::testHistogramAttribute(HistogramAttribute attribute) const
181 {
182  return d_data->attributes & attribute;
183 }
184 
185 void HistogramItem::draw(QPainter *painter, const QwtScaleMap &xMap,
186  const QwtScaleMap &yMap, const QRect &) const
187 {
188  const QwtIntervalData &iData = d_data->data;
189 
190  const int x0 = xMap.transform(baseline());
191  const int y0 = yMap.transform(baseline());
192 
193  for ( int i = 0; i < (int)iData.size(); i++ )
194  {
195  if ( d_data->attributes & HistogramItem::Xfy )
196  {
197  const int x2 = xMap.transform(iData.value(i));
198  if ( x2 == x0 )
199  continue;
200 
201  int y1 = yMap.transform( iData.interval(i).minValue());
202  int y2 = yMap.transform( iData.interval(i).maxValue());
203  if ( y1 > y2 )
204  qSwap(y1, y2);
205 
206  if ( i < (int)iData.size() - 2 )
207  {
208  const int yy1 = yMap.transform(iData.interval(i+1).minValue());
209  const int yy2 = yMap.transform(iData.interval(i+1).maxValue());
210 
211  if ( y2 == qwtMin(yy1, yy2) )
212  {
213  const int xx2 = xMap.transform(
214  iData.interval(i+1).minValue());
215  if ( xx2 != x0 && ( (xx2 < x0 && x2 < x0) ||
216  (xx2 > x0 && x2 > x0) ) )
217  {
218  // One pixel distance between neighboured bars
219  y2++;
220  }
221  }
222  }
223 
224  painter->setPen( QPen( color(i) ) );
225 
226  drawBar(painter, Qt::Horizontal,
227  QRect(x0, y1, x2 - x0, y2 - y1));
228  }
229  else
230  {
231  const int y2 = yMap.transform(iData.value(i));
232  if ( y2 == y0 )
233  continue;
234 
235  int x1 = xMap.transform(iData.interval(i).minValue());
236  int x2 = xMap.transform(iData.interval(i).maxValue());
237  if ( x1 > x2 )
238  qSwap(x1, x2);
239 
240  if ( i < (int)iData.size() - 2 )
241  {
242  const int xx1 = xMap.transform(iData.interval(i+1).minValue());
243  const int xx2 = xMap.transform(iData.interval(i+1).maxValue());
244 
245  if ( x2 == qwtMin(xx1, xx2) )
246  {
247  const int yy2 = yMap.transform(iData.value(i+1));
248  if ( yy2 != y0 && ( (yy2 < y0 && y2 < y0) || (yy2 > y0 && y2 > y0) ) )
249  {
250  // One pixel distance between neighboured bars
251  x2--;
252  }
253  }
254  }
255 
256  painter->setPen( QPen( color(i) ) );
257 
258  drawBar(painter, Qt::Vertical,
259  QRect(x1, y0, x2 - x1, y2 - y0) );
260  }
261  }
262 }
263 
264 void HistogramItem::drawBar(QPainter *painter,
265  Qt::Orientation, const QRect& rect) const
266 {
267  painter->save();
268 
269  const QColor color(painter->pen().color());
270  const QRect r = rect.normalized();
271 
272 
273  const int factor = 125;
274  const QColor light(color.light(factor));
275  const QColor dark(color.dark(factor));
276 
277  painter->setBrush(color);
278  painter->setPen(Qt::NoPen);
279  QwtPainter::drawRect(painter, r.x() + 1, r.y() + 1,
280  r.width() - 2, r.height() - 2);
281  painter->setBrush(Qt::NoBrush);
282 
283  painter->setPen(QPen(light, 2));
284 
285  QwtPainter::drawLine(painter,
286  r.left() + 1, r.top() + 2, r.right() + 1, r.top() + 2);
287 
288  painter->setPen(QPen(dark, 2));
289 
290  QwtPainter::drawLine(painter,
291  r.left() + 1, r.bottom(), r.right() + 1, r.bottom());
292 
293  painter->setPen(QPen(light, 1));
294 
295  QwtPainter::drawLine(painter,
296  r.left(), r.top() + 1, r.left(), r.bottom());
297  QwtPainter::drawLine(painter,
298  r.left() + 1, r.top() + 2, r.left() + 1, r.bottom() - 1);
299 
300 
301  painter->setPen(QPen(dark, 1));
302 
303  QwtPainter::drawLine(painter,
304  r.right() + 1, r.top() + 1, r.right() + 1, r.bottom());
305  QwtPainter::drawLine(painter,
306  r.right(), r.top() + 2, r.right(), r.bottom() - 1);
307 
308  painter->restore();
309 }
310 
311 #endif // QWT 5
312 
313 #endif // WITH_QWT
virtual void drawBar(QPainter *, Qt::Orientation o, const QRect &) const
Draws a single bar.
virtual ~HistogramItem()
Destructor.
void setData(const QwtIntervalData &data)
set data to render
virtual QwtDoubleRect boundingRect() const
Function hat will return the datas bounding rectangle (for rendering)
virtual void draw(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRect &) const
The actual draw function, drawing the bars inside the plot widget.
void setColors(std::vector< QColor > &_colors)
Set colors.
HistogramItem(const QString &title=QString::null)
Constructor.