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
79 HistogramItem::~HistogramItem()
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
HistogramItem::drawBar
virtual void drawBar(QPainter *, Qt::Orientation o, const QRect &) const
Draws a single bar.
HistogramItem::~HistogramItem
virtual ~HistogramItem()
Destructor.
HistogramItem::setData
void setData(const QwtIntervalData &data)
set data to render
HistogramItem::boundingRect
virtual QwtDoubleRect boundingRect() const
Function hat will return the datas bounding rectangle (for rendering)
HistogramItem::draw
virtual void draw(QPainter *, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRect &) const
The actual draw function, drawing the bars inside the plot widget.
HistogramItem::setColors
void setColors(std::vector< QColor > &_colors)
Set colors.
HistogramItem::HistogramItem
HistogramItem(const QString &title=QString::null)
Constructor.