|
Isis 3.0 Object Programmers' Reference |
Home |
00001 #include "HistogramItem.h" 00002 00003 #include <QPainter> 00004 #include <QScopedPointer> 00005 #include <QString> 00006 00007 #include <qwt_plot.h> 00008 #include <qwt_painter.h> 00009 #include <qwt_scale_map.h> 00010 #include <qwt_series_data.h> 00011 00012 #include <iostream> 00013 00014 namespace Isis { 00015 00021 class HistogramItem::PrivateData { 00022 public: 00023 int attributes; 00024 QScopedPointer<QwtIntervalSeriesData> data; 00025 QColor color; 00026 double reference; 00027 }; 00028 00035 HistogramItem::HistogramItem(const QwtText &title): QwtPlotItem() { 00036 init(); 00037 } 00038 00039 00046 HistogramItem::HistogramItem(const QString &title): QwtPlotItem(QwtText(title)) { 00047 init(); 00048 } 00049 00050 00055 HistogramItem::~HistogramItem() { 00056 delete d_data; 00057 } 00058 00059 00064 void HistogramItem::init() { 00065 d_data = new PrivateData(); 00066 d_data->data.reset(new QwtIntervalSeriesData()); 00067 d_data->reference = 0.0; 00068 d_data->attributes = HistogramItem::Auto; 00069 00070 setItemAttribute(QwtPlotItem::AutoScale, true); 00071 setItemAttribute(QwtPlotItem::Legend, true); 00072 00073 setZ(20.0); 00074 } 00075 00076 00083 void HistogramItem::setBaseline(double reference) { 00084 if(d_data->reference != reference) { 00085 d_data->reference = reference; 00086 itemChanged(); 00087 } 00088 } 00089 00090 00097 double HistogramItem::baseline() const { 00098 return d_data->reference; 00099 } 00100 00101 00108 void HistogramItem::setData(const QwtIntervalSeriesData &data) { 00109 d_data->data.reset(new QwtIntervalSeriesData(data)); 00110 itemChanged(); 00111 } 00112 00113 00120 const QwtIntervalSeriesData &HistogramItem::data() const { 00121 return *d_data->data; 00122 } 00123 00124 00131 void HistogramItem::setColor(const QColor &color) { 00132 if(d_data->color != color) { 00133 d_data->color = color; 00134 itemChanged(); 00135 } 00136 } 00137 00138 00145 QColor HistogramItem::color() const { 00146 return d_data->color; 00147 } 00148 00149 00156 QRectF HistogramItem::boundingRect() const { 00157 QRectF rect = d_data->data->boundingRect(); 00158 if(!rect.isValid()) 00159 return rect; 00160 00161 if(d_data->attributes & Xfy) { 00162 rect = QRectF(rect.y(), rect.x(), 00163 rect.height(), rect.width()); 00164 00165 if(rect.left() > d_data->reference) 00166 rect.setLeft(d_data->reference); 00167 else if(rect.right() < d_data->reference) 00168 rect.setRight(d_data->reference); 00169 } 00170 else { 00171 if(rect.bottom() < d_data->reference) 00172 rect.setBottom(d_data->reference); 00173 else if(rect.top() > d_data->reference) 00174 rect.setTop(d_data->reference); 00175 } 00176 00177 return rect; 00178 } 00179 00180 00187 int HistogramItem::rtti() const { 00188 return QwtPlotItem::Rtti_PlotHistogram; 00189 } 00190 00191 00199 void HistogramItem::setHistogramAttribute(HistogramAttribute attribute, bool on) { 00200 if(bool(d_data->attributes & attribute) == on) 00201 return; 00202 00203 if(on) 00204 d_data->attributes |= attribute; 00205 else 00206 d_data->attributes &= ~attribute; 00207 00208 itemChanged(); 00209 } 00210 00211 00220 bool HistogramItem::testHistogramAttribute(HistogramAttribute attribute) const { 00221 return d_data->attributes & attribute; 00222 } 00223 00224 00233 void HistogramItem::draw(QPainter *painter, const QwtScaleMap &xMap, 00234 const QwtScaleMap &yMap, const QRectF &) const { 00235 const QwtIntervalSeriesData &data = *d_data->data; 00236 00237 painter->setPen(QPen(d_data->color)); 00238 00239 const int x0 = xMap.transform(baseline()); 00240 const int y0 = yMap.transform(baseline()); 00241 00242 for(int i = 0; i < (int)data.size(); i++) { 00243 if(d_data->attributes & HistogramItem::Xfy) { 00244 const int x2 = xMap.transform(data.sample(i).value); 00245 if(x2 == x0) 00246 continue; 00247 00248 int y1 = yMap.transform(data.sample(i).interval.minValue()); 00249 int y2 = yMap.transform(data.sample(i).interval.maxValue()); 00250 if(y1 > y2) 00251 qSwap(y1, y2); 00252 00253 if(i < (int)data.size() - 2) { 00254 const int yy1 = yMap.transform(data.sample(i + 1).interval.minValue()); 00255 const int yy2 = yMap.transform(data.sample(i + 1).interval.maxValue()); 00256 00257 if(y2 == qMin(yy1, yy2)) { 00258 const int xx2 = xMap.transform( 00259 data.sample(i + 1).interval.minValue()); 00260 if(xx2 != x0 && ((xx2 < x0 && x2 < x0) || 00261 (xx2 > x0 && x2 > x0))) { 00262 // One pixel distance between neighboured bars 00263 y2++; 00264 } 00265 } 00266 } 00267 00268 drawBar(painter, Qt::Horizontal, 00269 QRect(x0, y1, x2 - x0, y2 - y1)); 00270 } 00271 else { 00272 const int y2 = yMap.transform(data.sample(i).value); 00273 if(y2 == y0) 00274 continue; 00275 00276 int x1 = xMap.transform(data.sample(i).interval.minValue()); 00277 int x2 = xMap.transform(data.sample(i).interval.maxValue()); 00278 if(x1 > x2) 00279 qSwap(x1, x2); 00280 00281 if(i < (int)data.size() - 2) { 00282 const int xx1 = xMap.transform(data.sample(i + 1).interval.minValue()); 00283 const int xx2 = xMap.transform(data.sample(i + 1).interval.maxValue()); 00284 00285 if(x2 == qMin(xx1, xx2)) { 00286 const int yy2 = yMap.transform(data.sample(i + 1).value); 00287 if(yy2 != y0 && ((yy2 < y0 && y2 < y0) || 00288 (yy2 > y0 && y2 > y0))) { 00289 // One pixel distance between neighboured bars 00290 x2--; 00291 } 00292 } 00293 } 00294 drawBar(painter, Qt::Vertical, 00295 QRect(x1, y0, x2 - x1, y2 - y0)); 00296 } 00297 } 00298 } 00299 00300 00308 void HistogramItem::drawBar(QPainter *painter, 00309 Qt::Orientation, const QRect &rect) const { 00310 painter->save(); 00311 00312 const QColor color(painter->pen().color()); 00313 const QRect r = rect.normalized(); 00314 00315 const int factor = 125; 00316 const QColor light(color.light(factor)); 00317 const QColor dark(color.dark(factor)); 00318 00319 painter->setBrush(color); 00320 painter->setPen(Qt::NoPen); 00321 QwtPainter::drawRect(painter, r.x() + 1, r.y() + 1, 00322 r.width() - 2, r.height() - 2); 00323 painter->setBrush(Qt::NoBrush); 00324 00325 painter->setPen(QPen(light, 2)); 00326 QwtPainter::drawLine(painter, 00327 r.left() + 1, r.top() + 2, r.right() + 1, r.top() + 2); 00328 00329 painter->setPen(QPen(dark, 2)); 00330 QwtPainter::drawLine(painter, 00331 r.left() + 1, r.bottom(), r.right() + 1, r.bottom()); 00332 00333 painter->setPen(QPen(light, 1)); 00334 00335 QwtPainter::drawLine(painter, 00336 r.left(), r.top() + 1, r.left(), r.bottom()); 00337 QwtPainter::drawLine(painter, 00338 r.left() + 1, r.top() + 2, r.left() + 1, r.bottom() - 1); 00339 00340 painter->setPen(QPen(dark, 1)); 00341 00342 QwtPainter::drawLine(painter, 00343 r.right() + 1, r.top() + 1, r.right() + 1, r.bottom()); 00344 QwtPainter::drawLine(painter, 00345 r.right(), r.top() + 2, r.right(), r.bottom() - 1); 00346 00347 painter->restore(); 00348 } 00349 00350 00357 QList <QPointF > HistogramItem::getVertices() const { 00358 return p_pointList; 00359 } 00360 00361 00367 void HistogramItem::setVertices(const QList <QPoint> &points) { 00368 double sample, line; 00369 p_pointList.clear(); 00370 for(int i = 0; getViewPort() && i < points.size(); i++) { 00371 getViewPort()->viewportToCube(points[i].x(), points[i].y(), sample, line); 00372 p_pointList.push_back(QPointF((sample), (line))); 00373 } 00374 } 00375 00376 00383 CubeViewport *HistogramItem::getViewPort() const { 00384 return p_cvp; 00385 } 00386 00387 00392 void HistogramItem::setViewPort(CubeViewport *cvp) { 00393 p_cvp = cvp; 00394 } 00395 }