USGS

Isis 3.0 Object Programmers' Reference

Home

HistogramItem.cpp

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 }