Commit b6fa603f authored by Dirk Wilden's avatar Dirk Wilden

enhanced histogram

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@5775 383ad7c9-94d9-4d36-a494-682f7c89f535
parent ee4c3f72
#include <qstring.h>
#include <qpainter.h>
#include <qwt_plot.h>
#include <qwt_interval_data.h>
#include <qwt_painter.h>
#include <qwt_scale_map.h>
#include "HistogramItem.hh"
class HistogramItem::PrivateData
{
public:
int attributes;
QwtIntervalData data;
std::vector< QColor > colors_;
double reference;
};
HistogramItem::HistogramItem(const QwtText &title):
QwtPlotItem(title)
{
init();
}
HistogramItem::HistogramItem(const QString &title):
QwtPlotItem(QwtText(title))
{
init();
}
HistogramItem::~HistogramItem()
{
delete d_data;
}
void HistogramItem::init()
{
d_data = new PrivateData();
d_data->reference = 0.0;
d_data->attributes = HistogramItem::Auto;
setItemAttribute(QwtPlotItem::AutoScale, true);
setItemAttribute(QwtPlotItem::Legend, true);
setZ(20.0);
}
void HistogramItem::setBaseline(double reference)
{
if ( d_data->reference != reference )
{
d_data->reference = reference;
itemChanged();
}
}
double HistogramItem::baseline() const
{
return d_data->reference;
}
void HistogramItem::setData(const QwtIntervalData &data)
{
d_data->data = data;
itemChanged();
}
const QwtIntervalData &HistogramItem::data() const
{
return d_data->data;
}
void HistogramItem::setColors( std::vector< QColor >& _colors)
{
d_data->colors_ = _colors;
itemChanged();
}
QColor HistogramItem::color(uint i) const
{
if ( i < d_data->colors_.size() )
return d_data->colors_[i];
else
return Qt::darkBlue;
}
QwtDoubleRect HistogramItem::boundingRect() const
{
QwtDoubleRect rect = d_data->data.boundingRect();
if ( !rect.isValid() )
return rect;
if ( d_data->attributes & Xfy )
{
rect = QwtDoubleRect( rect.y(), rect.x(),
rect.height(), rect.width() );
if ( rect.left() > d_data->reference )
rect.setLeft( d_data->reference );
else if ( rect.right() < d_data->reference )
rect.setRight( d_data->reference );
}
else
{
if ( rect.bottom() < d_data->reference )
rect.setBottom( d_data->reference );
else if ( rect.top() > d_data->reference )
rect.setTop( d_data->reference );
}
return rect;
}
int HistogramItem::rtti() const
{
return QwtPlotItem::Rtti_PlotHistogram;
}
void HistogramItem::setHistogramAttribute(HistogramAttribute attribute, bool on)
{
if ( bool(d_data->attributes & attribute) == on )
return;
if ( on )
d_data->attributes |= attribute;
else
d_data->attributes &= ~attribute;
itemChanged();
}
bool HistogramItem::testHistogramAttribute(HistogramAttribute attribute) const
{
return d_data->attributes & attribute;
}
void HistogramItem::draw(QPainter *painter, const QwtScaleMap &xMap,
const QwtScaleMap &yMap, const QRect &) const
{
const QwtIntervalData &iData = d_data->data;
const int x0 = xMap.transform(baseline());
const int y0 = yMap.transform(baseline());
for ( int i = 0; i < (int)iData.size(); i++ )
{
if ( d_data->attributes & HistogramItem::Xfy )
{
const int x2 = xMap.transform(iData.value(i));
if ( x2 == x0 )
continue;
int y1 = yMap.transform( iData.interval(i).minValue());
int y2 = yMap.transform( iData.interval(i).maxValue());
if ( y1 > y2 )
qSwap(y1, y2);
if ( i < (int)iData.size() - 2 )
{
const int yy1 = yMap.transform(iData.interval(i+1).minValue());
const int yy2 = yMap.transform(iData.interval(i+1).maxValue());
if ( y2 == qwtMin(yy1, yy2) )
{
const int xx2 = xMap.transform(
iData.interval(i+1).minValue());
if ( xx2 != x0 && ( (xx2 < x0 && x2 < x0) ||
(xx2 > x0 && x2 > x0) ) )
{
// One pixel distance between neighboured bars
y2++;
}
}
}
painter->setPen( QPen( color(i) ) );
drawBar(painter, Qt::Horizontal,
QRect(x0, y1, x2 - x0, y2 - y1));
}
else
{
const int y2 = yMap.transform(iData.value(i));
if ( y2 == y0 )
continue;
int x1 = xMap.transform(iData.interval(i).minValue());
int x2 = xMap.transform(iData.interval(i).maxValue());
if ( x1 > x2 )
qSwap(x1, x2);
if ( i < (int)iData.size() - 2 )
{
const int xx1 = xMap.transform(iData.interval(i+1).minValue());
const int xx2 = xMap.transform(iData.interval(i+1).maxValue());
if ( x2 == qwtMin(xx1, xx2) )
{
const int yy2 = yMap.transform(iData.value(i+1));
if ( yy2 != y0 && ( (yy2 < y0 && y2 < y0) ||
(yy2 > y0 && y2 > y0) ) )
{
// One pixel distance between neighboured bars
x2--;
}
}
}
painter->setPen( QPen( color(i) ) );
drawBar(painter, Qt::Vertical,
QRect(x1, y0, x2 - x1, y2 - y0) );
}
}
}
void HistogramItem::drawBar(QPainter *painter,
Qt::Orientation, const QRect& rect) const
{
painter->save();
const QColor color(painter->pen().color());
#if QT_VERSION >= 0x040000
const QRect r = rect.normalized();
#else
const QRect r = rect.normalize();
#endif
const int factor = 125;
const QColor light(color.light(factor));
const QColor dark(color.dark(factor));
painter->setBrush(color);
painter->setPen(Qt::NoPen);
QwtPainter::drawRect(painter, r.x() + 1, r.y() + 1,
r.width() - 2, r.height() - 2);
painter->setBrush(Qt::NoBrush);
painter->setPen(QPen(light, 2));
#if QT_VERSION >= 0x040000
QwtPainter::drawLine(painter,
r.left() + 1, r.top() + 2, r.right() + 1, r.top() + 2);
#else
QwtPainter::drawLine(painter,
r.left(), r.top() + 2, r.right() + 1, r.top() + 2);
#endif
painter->setPen(QPen(dark, 2));
#if QT_VERSION >= 0x040000
QwtPainter::drawLine(painter,
r.left() + 1, r.bottom(), r.right() + 1, r.bottom());
#else
QwtPainter::drawLine(painter,
r.left(), r.bottom(), r.right() + 1, r.bottom());
#endif
painter->setPen(QPen(light, 1));
#if QT_VERSION >= 0x040000
QwtPainter::drawLine(painter,
r.left(), r.top() + 1, r.left(), r.bottom());
QwtPainter::drawLine(painter,
r.left() + 1, r.top() + 2, r.left() + 1, r.bottom() - 1);
#else
QwtPainter::drawLine(painter,
r.left(), r.top() + 1, r.left(), r.bottom() + 1);
QwtPainter::drawLine(painter,
r.left() + 1, r.top() + 2, r.left() + 1, r.bottom());
#endif
painter->setPen(QPen(dark, 1));
#if QT_VERSION >= 0x040000
QwtPainter::drawLine(painter,
r.right() + 1, r.top() + 1, r.right() + 1, r.bottom());
QwtPainter::drawLine(painter,
r.right(), r.top() + 2, r.right(), r.bottom() - 1);
#else
QwtPainter::drawLine(painter,
r.right() + 1, r.top() + 1, r.right() + 1, r.bottom() + 1);
QwtPainter::drawLine(painter,
r.right(), r.top() + 2, r.right(), r.bottom());
#endif
painter->restore();
}
/* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
* Qwt Widget Library
* Copyright (C) 1997 Josef Wilgen
* Copyright (C) 2002 Uwe Rathmann
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the Qwt License, Version 1.0
*****************************************************************************/
#ifndef HISTOGRAM_ITEM_H
#define HISTOGRAM_ITEM_H
#include <qglobal.h>
#include <qcolor.h>
#include "qwt_plot_item.h"
class QwtIntervalData;
class QString;
class HistogramItem: public QwtPlotItem
{
public:
explicit HistogramItem(const QString &title = QString::null);
explicit HistogramItem(const QwtText &title);
virtual ~HistogramItem();
void setData(const QwtIntervalData &data);
const QwtIntervalData &data() const;
void setColors( std::vector< QColor >& _colors);
virtual QwtDoubleRect boundingRect() const;
virtual int rtti() const;
virtual void draw(QPainter *, const QwtScaleMap &xMap,
const QwtScaleMap &yMap, const QRect &) const;
void setBaseline(double reference);
double baseline() const;
enum HistogramAttribute
{
Auto = 0,
Xfy = 1
};
void setHistogramAttribute(HistogramAttribute, bool on = true);
bool testHistogramAttribute(HistogramAttribute) const;
protected:
virtual void drawBar(QPainter *,
Qt::Orientation o, const QRect &) const;
private:
QColor color(uint i) const;
void init();
class PrivateData;
PrivateData *d_data;
};
#endif
......@@ -17,6 +17,11 @@
#include <qlabel.h>
#include <qpainter.h>
#include <qwt_curve_fitter.h>
#include <qwt_interval_data.h>
#include <float.h>
#include <math.h>
//== NAMESPACES ===============================================================
......@@ -25,201 +30,195 @@ namespace ACG {
//== IMPLEMENTATION ==========================================================
void
QwtFunctionPlot::
add_function( std::vector<double>& _x,
std::vector<double>& _y,
const char* _title,
QColor _col )
/// Default constructor
QwtFunctionPlot::QwtFunctionPlot(QWidget* _parent) : QDialog( _parent ), Ui::QwtFunctionPlotBase()
{
// if color is white -> choose random color
QColor col = _col;
if( col.red() == 255 && col.green() == 255 && col.blue() == 255)
col.setRgb( (int)(30 + double(rand())/double(RAND_MAX)*200),
(int)(30 + double(rand())/double(RAND_MAX)*200),
(int)(30 + double(rand())/double(RAND_MAX)*200));
// create new curve and attach it to plot widget
QwtPlotCurve *curve = new QwtPlotCurve(_title);
curve->setData( &(_x[0]), &(_y[0]), std::min(_x.size(), _y.size()));
curve->setPen( QPen(col));
functions_.push_back(curve);
curve->attach( qwtPlot );
// check legend item
((QwtLegendItem*)legend_->find( curve))->setChecked(true);
// plot_zoomer_->setZoomBase(false);
update_zoom_base();
qwtPlot->replot();
}
setupUi( this );
// ------------------------------------------------------------------------------
plot_zoomer_ = new QwtPlotZoomer( qwtPlot->canvas());
// delete widget on close
setAttribute(Qt::WA_DeleteOnClose, true);
void
QwtFunctionPlot::
function_mode()
{
for(unsigned int i=0; i<functions_.size(); ++i)
{
functions_[i]->setStyle( QwtPlotCurve::Lines );
}
qwtPlot->replot();
histogram_ = new HistogramItem();
image_ = 0;
}
//------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
void QwtFunctionPlot::setFunction( std::vector<double>& _values)
{
values_ = _values;
//get min/max values
min_ = FLT_MAX;
max_ = FLT_MIN;
void
QwtFunctionPlot::
histogram_mode()
{
for(unsigned int i=0; i<functions_.size(); ++i)
{
functions_[i]->setStyle( QwtPlotCurve::Sticks );
for ( uint i=0; i < values_.size(); i++){
min_ = std::min(min_, values_[i] );
max_ = std::max(max_, values_[i] );
}
qwtPlot->replot();
}
// ------------------------------------------------------------------------------
}
//------------------------------------------------------------------------------
void
QwtFunctionPlot::
linear_scaling()
void QwtFunctionPlot::setParameters(bool _repeat, double _repeatMax,
bool _clamp, double _clampMin, double _clampMax,
bool _center,
bool _absolute,
bool _scale)
{
// qwtPlot->setAxisScaleEngine(1, (QwtScaleEngine*)linear_scale_engine_);
// qwtPlot->replot();
repeat_ = _repeat;
repeatMax_ = _repeatMax;
clamp_ = _clamp;
clampMin_ = _clampMin;
clampMax_ = _clampMax;
center_ = _center;
absolute_ = _absolute;
scale_ = _scale;
}
//------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
void
QwtFunctionPlot::
logarithmic_scaling()
void QwtFunctionPlot::setImage(QImage* _image)
{
// qwtPlot->setAxisScaleEngine( 1, (QwtScaleEngine*)log10_scale_engine_);
// qwtPlot->replot();
image_ = _image;
}
//------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
double QwtFunctionPlot::transform( double _value ){
if (absolute_)
_value = fabs(_value);
void
QwtFunctionPlot::
update_pens(int _inc)
{
for(unsigned int i=0; i<functions_.size(); ++i)
{
QPen pen = functions_[i]->pen();
if (clamp_){
_value = std::max( clampMin_, _value );
_value = std::min( clampMax_, _value );
}
if (repeat_){
_value = ( (_value - currentMin_) / (currentMax_-currentMin_) ) * repeatMax_;
}else{
pen.setWidth( std::max(1,(int)pen.width() + _inc) );
if (center_)
_value -= (currentMax_-currentMin_) / 2.0; //TODO:thats wrong
functions_[i]->setPen( pen);
if (scale_)
_value = (_value - currentMin_) / (currentMax_-currentMin_);
if (center_)
_value += 0.5;
}
qwtPlot->replot();
return _value;
}
//------------------------------------------------------------------------------
// ------------------------------------------------------------------------------
void QwtFunctionPlot::initValues()
{
//get min/max values
currentMin_ = FLT_MAX;
currentMax_ = FLT_MIN;
void
QwtFunctionPlot::
add_function( std::vector<double>& _y,
const char* _title,
QColor _col )
{
// set up uniform x-vector
std::vector<double> x(_y.size());
for(unsigned int i=0; i<x.size(); ++i)
x[i] = i;
for ( uint i=0; i < values_.size(); i++){
add_function( x, _y, _title, _col);
}
double tranformed = values_[i];
if (absolute_)
tranformed = fabs(tranformed);
// ------------------------------------------------------------------------------
if (clamp_){
tranformed = std::max( clampMin_, tranformed );
tranformed = std::min( clampMax_, tranformed );
}
currentMin_ = std::min(currentMin_, tranformed );
currentMax_ = std::max(currentMax_, tranformed );
}
}
//------------------------------------------------------------------------------
void
QwtFunctionPlot::
slotLegendChecked(QwtPlotItem* _plot_item, bool _visible)
void QwtFunctionPlot::replot()
{
// only draw checked curves
_plot_item->setVisible(_visible);
update_zoom_base();
qwtPlot->replot();
}
initValues();
// ------------------------------------------------------------------------------
//create intervals
const int intervalCount = 100;
QwtArray<QwtDoubleInterval> intervals(intervalCount);
QwtArray<double> count(intervalCount);
std::vector< QColor > colors;
void
QwtFunctionPlot::
update_zoom_base()
{
QwtDoubleRect rect;
for(unsigned int i=0; i<functions_.size(); ++i)
{
if(functions_[i]->isVisible())
rect |= functions_[i]->boundingRect();
}
if( rect.isValid())
double pos = transform(min_);
double width = ( transform(max_) - transform(min_) ) / intervalCount;
QColor lastColor = Qt::black;
for ( int i = 0; i < (int)intervals.size(); i++ )
{
plot_zoomer_->setZoomBase( rect );
}
}
intervals[i] = QwtDoubleInterval(pos, pos + width);
pos += width;
//compute a color for the given interval
if (image_ != 0){
double intervalCenter = pos + (width/2.0);
// ------------------------------------------------------------------------------
if (intervalCenter > 1.0 && !repeat_){
colors.push_back( lastColor );
continue;
}
if ( intervalCenter < 0.0){
colors.push_back( lastColor );
continue;
}
void
QwtFunctionPlot::
keyPressEvent ( QKeyEvent* _event )
{
switch( _event->key())
{
case Qt::Key_H:
{
std::cerr << "histogram mode...\n";
histogram_mode();
break;
}
case Qt::Key_F:
{
std::cerr << "function mode...\n";
function_mode();
break;
}