From 672cc152c6cac74e1c8862b5bb24a15a884ee222 Mon Sep 17 00:00:00 2001 From: nds Date: Thu, 6 Mar 2008 06:52:49 +0000 Subject: [PATCH] Method EraseAll is corrected to clear by hands all objects. Improve method updateTitles() for title of the second axis. --- src/Plot2d/Plot2d_Curve.cxx | 2 +- src/Plot2d/Plot2d_Histogram.cxx | 218 +++++++++++++ src/Plot2d/Plot2d_Histogram.h | 55 ++++ src/Plot2d/Plot2d_HistogramItem.cxx | 480 ++++++++++++++++++++++++++++ src/Plot2d/Plot2d_HistogramItem.h | 99 ++++++ src/Plot2d/Plot2d_Object.cxx | 28 +- src/Plot2d/Plot2d_Object.h | 3 + src/Plot2d/Plot2d_ViewFrame.cxx | 36 ++- 8 files changed, 913 insertions(+), 8 deletions(-) create mode 100644 src/Plot2d/Plot2d_Histogram.cxx create mode 100644 src/Plot2d/Plot2d_Histogram.h create mode 100644 src/Plot2d/Plot2d_HistogramItem.cxx create mode 100644 src/Plot2d/Plot2d_HistogramItem.h diff --git a/src/Plot2d/Plot2d_Curve.cxx b/src/Plot2d/Plot2d_Curve.cxx index 38b7a358a..43e91a991 100755 --- a/src/Plot2d/Plot2d_Curve.cxx +++ b/src/Plot2d/Plot2d_Curve.cxx @@ -113,6 +113,7 @@ void Plot2d_Curve::updatePlotItem( QwtPlotItem* theItem ) if ( !aCurve ) return; + Plot2d_Object::updatePlotItem( theItem ); Qt::PenStyle ps = Plot2d::plot2qwtLine( getLine() ); QwtSymbol::Style ms = Plot2d::plot2qwtMarker( getMarker() ); @@ -121,7 +122,6 @@ void Plot2d_Curve::updatePlotItem( QwtPlotItem* theItem ) QPen( getColor() ), QSize( myMarkerSize, myMarkerSize ) ) ); aCurve->setData( horData(), verData(), nbPoints() ); - aCurve->setTitle( !getName().isEmpty() ? getName() : getVerTitle() ); } /*! diff --git a/src/Plot2d/Plot2d_Histogram.cxx b/src/Plot2d/Plot2d_Histogram.cxx new file mode 100644 index 000000000..556201faa --- /dev/null +++ b/src/Plot2d/Plot2d_Histogram.cxx @@ -0,0 +1,218 @@ +// Name : Plot2d_Histogram.cpp +// Purpose: Implementation of Plot2d_Histogram class. +// +// History: +// 11/12/07 - Natalia Ermolaeva - Creation of the file + +#include + +#include +#include +#include + +#include +#include + +/** + * Constructor. + */ +Plot2d_Histogram::Plot2d_Histogram() + : m_dWidth( 0 ), m_dDefWidth( 0 ) +{ +} + +/** + * Destructor. + */ +Plot2d_Histogram::~Plot2d_Histogram() +{ +} + +/** + * + */ +int Plot2d_Histogram::rtti() +{ + return QwtPlotItem::Rtti_PlotHistogram; +} + +/*! + Displays curve in the given plot. +*/ +QwtPlotItem* Plot2d_Histogram::createPlotItem() +{ + Plot2d_HistogramItem* anItem = new Plot2d_HistogramItem(); + updatePlotItem( anItem ); + return anItem; +} + +/** + * Auto fill parameters of object by plot view + */ +void Plot2d_Histogram::autoFill( const QwtPlot* thePlot ) +{ + setColor( getNextColor( thePlot ) ); +} + +/*! + * Updates curve fields + */ +void Plot2d_Histogram::updatePlotItem( QwtPlotItem* theItem ) +{ + if ( theItem->rtti() != rtti() ) + return; + Plot2d_HistogramItem* anItem = dynamic_cast + ( theItem ); + if ( !anItem ) + return; + Plot2d_Object::updatePlotItem( theItem ); + + anItem->setData( getData() ); + anItem->setColor( getColor() ); +} + +/** + * Sets data to object + */ +void Plot2d_Histogram::setData( const QList& theXVals, + const QList& theYVals ) +{ + pointList aPoints; + int aSize = theXVals.size(); + for ( int i = 0; i < aSize; i++ ) { + Plot2d_Point aPoint; + aPoint.x = theXVals[i]; + aPoint.y = theYVals[i]; + aPoint.text = QString(); + aPoints.append( aPoint ); + } + setPointList( aPoints ); + + m_dDefWidth = getMinInterval( theXVals )*(2./3.); + m_dWidth = m_dDefWidth; +} + +/** + * Returns data + */ +QwtIntervalData Plot2d_Histogram::getData() const +{ + pointList aPoints = getPointList(); + int aSize = aPoints.size(); + + QwtArray anIntervals( aSize ); + QwtArray aValues( aSize ); + double aX; + double aWidth = isAutoAssign() ? m_dDefWidth : m_dWidth; + for ( int i = 0; i < aSize; i++ ) { + aX = aPoints[i].x; + anIntervals[i] = QwtDoubleInterval( aX - aWidth/2, aX + aWidth/2 ); + aValues[i] = aPoints[i].y; + } + + return QwtIntervalData( anIntervals, aValues ); +} + +/** + * Returns color of histogram + */ +QColor Plot2d_Histogram::getColor() const +{ + return m_Color; +} + +/** + * Sets color of histogram + */ +void Plot2d_Histogram::setColor( const QColor& theColor ) +{ + m_Color = theColor; + setAutoAssign( false ); +} + +/** + * Returns width for a histogram bar + */ +double Plot2d_Histogram::getWidth( const bool& isDef ) const +{ + return isDef ? m_dDefWidth : m_dWidth; +} + +/** + * Sets width of a histogram bar + */ +void Plot2d_Histogram::setWidth( const double theWidth ) +{ + m_dWidth = theWidth; + setAutoAssign( false ); +} + +/** + * + */ +QColor Plot2d_Histogram::getNextColor( const QwtPlot* thePlot ) +{ + bool bOk = false; + QColor aColor; + while ( !bOk ) { + int aRed = (int)( 256.0 * rand() / RAND_MAX); // generate random color + int aGreen = (int)( 256.0 * rand() / RAND_MAX); // ... + int aBlue = (int)( 256.0 * rand() / RAND_MAX); // ... + aColor = QColor( aRed, aGreen, aBlue ); + bOk = !existColor( thePlot, aColor ); + } + return aColor; +} + +/** + * + */ +bool Plot2d_Histogram::existColor( const QwtPlot* thePlot, const QColor& theColor) +{ + QColor aColor = thePlot->palette().color( QPalette::Background ); + if ( closeColors( theColor, aColor ) ) + return true; + QwtPlotItemList anItems = thePlot->itemList(); + QwtPlotItemIterator anIt = anItems.begin(), aLast = anItems.end(); + QwtPlotItem* anItem; + for( ; anIt != aLast; anIt++ ) { + anItem = *anIt; + if ( !anItem ) + continue; + if( anItem->rtti() == rtti() ) { + Plot2d_Histogram* anItem = dynamic_cast + ( anItem ); + if ( anItem && aColor == anItem->getColor() ) + return true; + } + else if ( anItem->rtti() == QwtPlotItem::Rtti_PlotCurve ) { + QwtPlotCurve* aCurve = dynamic_cast( anItem ); + if ( aCurve ) { + if ( aCurve && aCurve->pen().color() == aColor ) + return true; + } + } + } + return false; +} + +/** + * Return min interval from values + */ +double Plot2d_Histogram::getMinInterval( const QList& theVals ) +{ + double aValue = -1; + int aSize = theVals.size(); + if ( aSize < 2 ) + return aValue; + + aValue = fabs( theVals[1] - theVals[0] ); + double aDelta; + for ( int i = 2; i < aSize; i++ ) { + aDelta = fabs( theVals[i] - theVals[i-1] ); + if ( aDelta < aValue && aDelta ) + aValue = aDelta; + } + return aValue/2; +} + diff --git a/src/Plot2d/Plot2d_Histogram.h b/src/Plot2d/Plot2d_Histogram.h new file mode 100644 index 000000000..7703c8213 --- /dev/null +++ b/src/Plot2d/Plot2d_Histogram.h @@ -0,0 +1,55 @@ +// Name : Plot2d_Histogram.h +// Purpose: Plot2d_Histogram is a class which defines histogram +// plot item. +// +// History: +// 11/12/07 - Natalia Ermolaeva - Creation of the file + +#ifndef PLOT2D_HISTOGRAM_H +#define PLOT2D_HISTOGRAM_H + +#include "Plot2d.h" +#include "Plot2d_HistogramItem.h" +#include "Plot2d_Object.h" + +class QString; +class QColor; +class QwtIntervalData; + +class PLOT2D_EXPORT Plot2d_Histogram : public Plot2d_Object +{ +public: + Plot2d_Histogram(); + virtual ~Plot2d_Histogram(); + + virtual int rtti(); + virtual QwtPlotItem* createPlotItem(); + virtual void autoFill( const QwtPlot* ); + virtual void updatePlotItem( QwtPlotItem* ); + + void setData( const QList&, const QList& ); + QwtIntervalData getData() const; + + QColor getColor() const; + void setColor( const QColor& ); + double getWidth( const bool& ) const; + void setWidth( const double ); + + static double getMinInterval( const QList& ); + +protected: + QColor getNextColor( const QwtPlot* ); + bool existColor( const QwtPlot*, const QColor& ); + +private: + QColor m_Color; + double m_dWidth; + double m_dDefWidth; +}; + + +#if defined WIN32 +#pragma warning( default: 4251 ) +#endif + +#endif diff --git a/src/Plot2d/Plot2d_HistogramItem.cxx b/src/Plot2d/Plot2d_HistogramItem.cxx new file mode 100644 index 000000000..5b503c714 --- /dev/null +++ b/src/Plot2d/Plot2d_HistogramItem.cxx @@ -0,0 +1,480 @@ +// Name : Plot2d_HistogramItem.cpp +// Purpose: Implementation of Plot2d_HistogramItem class. +// +// History: +// 11/12/07 - Natalia Ermolaeva - Creation of the file + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/** + * Constructor + */ +Plot2d_HistogramQwtItem::Plot2d_HistogramQwtItem( const QwtText& theTitle ) +: QwtPlotItem( theTitle ) +{ + init(); +} + +/** + * Constructor + */ +Plot2d_HistogramQwtItem::Plot2d_HistogramQwtItem( const QString& theTitle ) +: QwtPlotItem( QwtText( theTitle ) ) +{ + init(); +} + +/** + * Destructor + */ +Plot2d_HistogramQwtItem::~Plot2d_HistogramQwtItem() +{ + delete m_pData; +} + +/** + * Initialization of object + */ +void Plot2d_HistogramQwtItem::init() +{ + m_pData = new PrivateData(); + m_pData->reference = 0.0; + m_pData->attributes = Plot2d_HistogramQwtItem::Auto; + + setItemAttribute( QwtPlotItem::AutoScale, true ); + setItemAttribute( QwtPlotItem::Legend, true ); + + setZ( 20.0 ); +} +/** + * Sets base line to object + * @param theRef + */ +void Plot2d_HistogramQwtItem::setBaseline( double theRef ) +{ + if ( m_pData->reference != theRef ) { + m_pData->reference = theRef; + itemChanged(); + } +} + +/** + * Returns base line of object + */ +double Plot2d_HistogramQwtItem::baseline() const +{ + return m_pData->reference; +} + +/** + * Sets data to object + */ +void Plot2d_HistogramQwtItem::setData( const QwtIntervalData& theData ) +{ + m_pData->data = theData; + itemChanged(); +} + +/** + * Returns data from object + */ +const QwtIntervalData &Plot2d_HistogramQwtItem::data() const +{ + return m_pData->data; +} + +/** + * Sets color to object + */ +void Plot2d_HistogramQwtItem::setColor( const QColor& theColor ) +{ + if ( m_pData->color != theColor ) { + m_pData->color = theColor; + itemChanged(); + } +} +/** + * Returns color from object + */ +QColor Plot2d_HistogramQwtItem::color() const +{ + return m_pData->color; +} + +/** + * Returns bounding rect of object + */ +QwtDoubleRect Plot2d_HistogramQwtItem::boundingRect() const +{ + QwtDoubleRect aRect = m_pData->data.boundingRect(); + if ( !aRect.isValid() ) + return aRect; + + if ( m_pData->attributes & Xfy ) { + aRect = QwtDoubleRect( aRect.y(), aRect.x(), + aRect.height(), aRect.width() ); + if ( aRect.left() > m_pData->reference ) + aRect.setLeft( m_pData->reference ); + else if ( aRect.right() < m_pData->reference ) + aRect.setRight( m_pData->reference ); + } + else { + if ( aRect.bottom() < m_pData->reference ) + aRect.setBottom( m_pData->reference ); + else if ( aRect.top() > m_pData->reference ) + aRect.setTop( m_pData->reference ); + } + return aRect; +} + +/** + * Returns type of plot object + */ +int Plot2d_HistogramQwtItem::rtti() const +{ + return QwtPlotItem::Rtti_PlotHistogram; +} +/** + * Sets histogram attributes + */ +void Plot2d_HistogramQwtItem::setHistogramAttribute( HistogramAttribute theAttr, + bool isOn ) +{ + if ( bool( m_pData->attributes & theAttr ) == isOn ) + return; + + if ( isOn ) + m_pData->attributes |= theAttr; + else + m_pData->attributes &= ~theAttr; + + itemChanged(); +} + +/** + * Tests histogram attributes + */ +bool Plot2d_HistogramQwtItem::testHistogramAttribute( + HistogramAttribute theAttr ) const +{ + return m_pData->attributes & theAttr; +} + +/** + * Draws histogram object + */ +void Plot2d_HistogramQwtItem::draw( QPainter *thePainter, + const QwtScaleMap& theXMap, + const QwtScaleMap& theYMap, + const QRect& ) const +{ + const QwtIntervalData &iData = m_pData->data; + thePainter->setPen( QPen( m_pData->color ) ); + + const int x0 = theXMap.transform( baseline() ); + const int y0 = theYMap.transform( baseline() ); + + for ( int i = 0; i < (int)iData.size(); i++ ) { + if ( m_pData->attributes & Plot2d_HistogramQwtItem::Xfy ) { + const int x2 = theXMap.transform( iData.value( i ) ); + if ( x2 == x0 ) + continue; + int y1 = theYMap.transform( iData.interval( i ).minValue() ); + int y2 = theYMap.transform( iData.interval( i ).maxValue() ); + if ( y1 > y2 ) + qSwap( y1, y2 ); + + if ( i < (int)iData.size() - 2 ) { + const int yy1 = theYMap.transform( iData.interval(i+1).minValue() ); + const int yy2 = theYMap.transform( iData.interval(i+1).maxValue() ); + if ( y2 == qwtMin( yy1, yy2 ) ) { + const int xx2 = theXMap.transform( iData.interval(i+1).minValue() ); + if ( xx2 != x0 && ( ( xx2 < x0 && x2 < x0 ) || + ( xx2 > x0 && x2 > x0 ) ) ) { + // One pixel distance between neighboured bars + y2++; + } + } + } + drawBar( thePainter, Qt::Horizontal, QRect( x0, y1, x2 - x0, y2 - y1 ) ); + } + else { + const int y2 = theYMap.transform( iData.value( i ) ); + if ( y2 == y0 ) + continue; + int x1 = theXMap.transform( iData.interval( i ).minValue() ); + int x2 = theXMap.transform( iData.interval( i ).maxValue() ); + if ( x1 > x2 ) + qSwap( x1, x2 ); + + if ( i < (int)iData.size() - 2 ) { + const int xx1 = theXMap.transform( iData.interval(i+1).minValue() ); + const int xx2 = theXMap.transform( iData.interval(i+1).maxValue() ); + if ( x2 == qwtMin( xx1, xx2 ) ) { + const int yy2 = theYMap.transform( iData.value(i+1) ); + if ( yy2 != y0 && ( ( yy2 < y0 && y2 < y0 ) || + ( yy2 > y0 && y2 > y0 ) ) ) { + // One pixel distance between neighboured bars + x2--; + } + } + } + drawBar( thePainter, Qt::Vertical, QRect( x1, y0, x2 - x1, y2 - y0 ) ); + } + } +} + +/** + * Draws bar of histogram + */ +void Plot2d_HistogramQwtItem::drawBar( QPainter* thePainter, + Qt::Orientation, + const QRect& theRect ) const +{ + thePainter->save(); + + const QColor color( thePainter->pen().color() ); +#if QT_VERSION >= 0x040000 + QRect r = theRect.normalized(); +#else + QRect r = theRect.normalize(); +#endif + + const int factor = 125; + const QColor light( color.light( factor ) ); + const QColor dark( color.dark( factor ) ); + + thePainter->setBrush( color ); + thePainter->setPen( Qt::NoPen ); + QwtPainter::drawRect( thePainter, r.x() + 1, r.y() + 1, + r.width() - 2, r.height() - 2 ); + thePainter->setBrush( Qt::NoBrush ); + + thePainter->setPen( QPen( light, 2 ) ); +#if QT_VERSION >= 0x040000 + QwtPainter::drawLine( thePainter, r.left() + 1, r.top() + 2, + r.right() + 1, r.top() + 2 ); +#else + QwtPainter::drawLine( thePainter, r.left(), r.top() + 2, + r.right() + 1, r.top() + 2 ); +#endif + + thePainter->setPen( QPen( dark, 2 ) ); +#if QT_VERSION >= 0x040000 + QwtPainter::drawLine( thePainter, r.left() + 1, r.bottom(), + r.right() + 1, r.bottom() ); +#else + QwtPainter::drawLine( thePainter, r.left(), r.bottom(), + r.right() + 1, r.bottom()); +#endif + thePainter->setPen( QPen( light, 1 ) ); + +#if QT_VERSION >= 0x040000 + QwtPainter::drawLine( thePainter, r.left(), r.top() + 1, + r.left(), r.bottom() ); + QwtPainter::drawLine( thePainter, r.left() + 1, r.top() + 2, + r.left() + 1, r.bottom() - 1 ); +#else + QwtPainter::drawLine( thePainter, r.left(), r.top() + 1, + r.left(), r.bottom() + 1 ); + QwtPainter::drawLine( thePainter, r.left() + 1, r.top() + 2, + r.left() + 1, r.bottom() ); +#endif + thePainter->setPen( QPen( dark, 1 ) ); + +#if QT_VERSION >= 0x040000 + QwtPainter::drawLine( thePainter, r.right() + 1, r.top() + 1, + r.right() + 1, r.bottom() ); + QwtPainter::drawLine(thePainter, r.right(), r.top() + 2, + r.right(), r.bottom() - 1 ); +#else + QwtPainter::drawLine( thePainter, r.right() + 1, r.top() + 1, + r.right() + 1, r.bottom() + 1 ); + QwtPainter::drawLine( thePainter, r.right(), r.top() + 2, + r.right(), r.bottom() ); +#endif + thePainter->restore(); +} + +/** + * Constructor + */ +Plot2d_HistogramItem::Plot2d_HistogramItem( const QwtText& theTitle ) +: Plot2d_HistogramQwtItem( theTitle ), m_bCrossed( true ) +{ +} + +/** + * Constructor + */ +Plot2d_HistogramItem::Plot2d_HistogramItem( const QString& theTitle ) +: Plot2d_HistogramQwtItem( theTitle ), m_bCrossed( true ) +{ +} + +/** + * Destructor + */ +Plot2d_HistogramItem::~Plot2d_HistogramItem() +{ +} + +/** + * Set to legend item symbol with color of item + */ +void Plot2d_HistogramItem::updateLegend( QwtLegend* theLegend ) const +{ + if ( !theLegend ) + return; + QwtPlotItem::updateLegend( theLegend ); + QWidget* theWidget = theLegend->find( this ); + if ( !theWidget || !theWidget->inherits( "QwtLegendItem" ) ) + return; + QwtLegendItem* anItem = ( QwtLegendItem* )theWidget; + QFontMetrics aFMetrics( anItem->font() ); + int aSize = aFMetrics.height(); + QwtSymbol aSymbol( QwtSymbol::Rect, QBrush( color() ), + QPen( color() ), QSize( aSize, aSize ) ); + anItem->setSymbol( aSymbol ); + anItem->setIdentifierMode( theLegend->identifierMode() + | QwtLegendItem::ShowSymbol ); + anItem->update(); +} + +/** + * Draws histogram object + */ +void Plot2d_HistogramItem::draw( QPainter *thePainter, + const QwtScaleMap& theXMap, + const QwtScaleMap& theYMap, + const QRect& ) const +{ + // nds: clear list of bar items + Plot2d_HistogramItem* anItem = (Plot2d_HistogramItem*)this; + anItem->m_BarItems.clear(); + + const QwtIntervalData &iData = m_pData->data; + thePainter->setPen( QPen( m_pData->color ) ); + const int x0 = theXMap.transform( baseline() ); + const int y0 = theYMap.transform( baseline() ); + + for ( int i = 0; i < (int)iData.size(); i++ ) { + if ( m_pData->attributes & Plot2d_HistogramItem::Xfy ) { + const int x2 = theXMap.transform( iData.value( i ) ); + if ( x2 == x0 ) + continue; + int y1 = theYMap.transform( iData.interval( i ).minValue() ); + int y2 = theYMap.transform( iData.interval( i ).maxValue() ); + if ( y1 > y2 ) + qSwap( y1, y2 ); + + if ( i < (int)iData.size() - 2 ) { + const int yy1 = theYMap.transform( iData.interval(i+1).minValue() ); + const int yy2 = theYMap.transform( iData.interval(i+1).maxValue() ); + if ( y2 == qwtMin( yy1, yy2 ) ) { + const int xx2 = theXMap.transform( iData.interval(i+1).minValue() ); + if ( xx2 != x0 && ( ( xx2 < x0 && x2 < x0 ) || + ( xx2 > x0 && x2 > x0 ) ) ) { + // One pixel distance between neighboured bars + y2++; + } + } + } + // nds: draw rect with the other lower rects + QRect aRect( x0, y1, x2 - x0, y2 - y1 ); + drawRectAndLowers( thePainter, Qt::Horizontal, aRect ); + anItem->m_BarItems.append( aRect ); + } + else { + const int y2 = theYMap.transform( iData.value( i ) ); + if ( y2 == y0 ) + continue; + int x1 = theXMap.transform( iData.interval( i ).minValue() ); + int x2 = theXMap.transform( iData.interval( i ).maxValue() ); + if ( x1 > x2 ) + qSwap( x1, x2 ); + + if ( i < (int)iData.size() - 2 ) { + const int xx1 = theXMap.transform( iData.interval(i+1).minValue() ); + const int xx2 = theXMap.transform( iData.interval(i+1).maxValue() ); + if ( x2 == qwtMin( xx1, xx2 ) ) { + const int yy2 = theYMap.transform( iData.value(i+1) ); + if ( yy2 != y0 && ( ( yy2 < y0 && y2 < y0 ) || + ( yy2 > y0 && y2 > y0 ) ) ) { + // One pixel distance between neighboured bars + x2--; + } + } + } + // nds: draw rect with the other lower rects + QRect aRect(x1, y0, x2 - x1, y2 - y0 ); + drawRectAndLowers( thePainter, Qt::Vertical, aRect ); + anItem->m_BarItems.append( aRect ); + } + } +} + +/** + * Draws bar of histogram and on it bars of histograms with lower height. + */ +void Plot2d_HistogramItem::drawRectAndLowers( QPainter* thePainter, + Qt::Orientation theOr, + const QRect& theRect ) const +{ + QRect aRect = theRect; + // theRect has inversed coordinates on Y axis. The top of the rect is bottom in standard QRect coordinates, and it bottom is the top. + if ( m_bCrossed && theOr == Qt::Horizontal ) + aRect.setTop( getCrossedTop( theRect ) ); + + drawBar( thePainter, Qt::Horizontal, aRect ); +} + +/** + * Returns top value of the given rect in the context of other bars. + * It's necessary to remember, that theRecs has inverted coordinate Y. + */ +int Plot2d_HistogramItem::getCrossedTop( const QRect& theRect ) const +{ + int aRes = theRect.top(); + QwtPlot* aPlot = plot(); + int aHeight = theRect.height(); + if ( aPlot ) { + QwtPlotItemList anItems = aPlot->itemList(); + QwtPlotItemIterator anIt = anItems.begin(), aLast = anItems.end(); + Plot2d_HistogramItem* anItem; + QList aRects; + for ( ; anIt != aLast; anIt++ ) { + if ( !(*anIt)->rtti() == QwtPlotItem::Rtti_PlotHistogram ) + continue; + anItem = dynamic_cast( *anIt ); + if( !anItem || anItem == this ) + continue; + aRects.clear(); + aRects = anItem->getBars(); + for ( int i = 0, aSize = aRects.size(); i < aSize; i++ ) { + if ( qMax( theRect.x(), aRects[i].x() ) <= + qMin( theRect.left(), aRects[i].left() ) ) { + if ( theRect.bottom() < aRects[i].bottom() ) + if ( aRects[i].bottom() < aRes ) + aRes = aRects[i].bottom(); + } + } + } + } + return aRes; +} + diff --git a/src/Plot2d/Plot2d_HistogramItem.h b/src/Plot2d/Plot2d_HistogramItem.h new file mode 100644 index 000000000..37408a165 --- /dev/null +++ b/src/Plot2d/Plot2d_HistogramItem.h @@ -0,0 +1,99 @@ +// Name : Plot2d_HistogramItem.h +// Purpose: Plot2d_HistogramItem is a class of building histogram +// object. Appends legend items with symbol. +// Appends crossed bars. +// +// History: +// 11/12/07 - Natalia Ermolaeva - Creation of the file + +#ifndef PLOT2D_HISTOGRAM_ITEM_H +#define PLOT2D_HISTOGRAM_ITEM_H + +#include + +#include +#include +#include "qwt_plot_item.h" +#include "qwt_interval_data.h" +#include "QColor" + +#include + +class QwtIntervalData; +class QwtLegend; +class QString; + +class Plot2d_HistogramQwtItem: public QwtPlotItem +{ +protected: + class PrivateData { + public: + int attributes; + QwtIntervalData data; + QColor color; + double reference; + }; +public: + explicit Plot2d_HistogramQwtItem( const QString& = QString::null ); + explicit Plot2d_HistogramQwtItem( const QwtText& ); + virtual ~Plot2d_HistogramQwtItem(); + + void setData( const QwtIntervalData& ); + const QwtIntervalData& data() const; + + void setColor( const QColor & ); + QColor color() const; + + virtual QwtDoubleRect boundingRect() const; + virtual int rtti() const; + virtual void draw( QPainter *, const QwtScaleMap &xMap, + const QwtScaleMap &yMap, const QRect & ) const; + + void setBaseline( double ); + double baseline() const; + + enum HistogramAttribute { + Auto = 0, + Xfy = 1 + }; + + void setHistogramAttribute( HistogramAttribute, bool = true ); + bool testHistogramAttribute( HistogramAttribute ) const; + +protected: + virtual void drawBar(QPainter* , Qt::Orientation, const QRect& ) const; + +protected: + void init(); + + class PrivateData; + PrivateData* m_pData; +}; + +class PLOT2D_EXPORT Plot2d_HistogramItem : public Plot2d_HistogramQwtItem +{ +public: + explicit Plot2d_HistogramItem( const QString& = QString::null ); + explicit Plot2d_HistogramItem( const QwtText& ); + virtual ~Plot2d_HistogramItem(); + + QList getBars() const { return m_BarItems; }; + + virtual void updateLegend( QwtLegend* ) const; + virtual void draw( QPainter *, const QwtScaleMap &xMap, + const QwtScaleMap &yMap, const QRect & ) const; + void drawBarRect( QPainter*, const QRect& ) const; + + void setCrossItems( const bool& theCross ) { m_bCrossed = theCross; } + bool isCrossItems() const { return m_bCrossed; } + +private: + void drawRectAndLowers( QPainter* , Qt::Orientation, const QRect& ) const; + int getCrossedTop( const QRect& ) const; + +private: + QList m_BarItems; + bool m_bCrossed; +}; + +#endif diff --git a/src/Plot2d/Plot2d_Object.cxx b/src/Plot2d/Plot2d_Object.cxx index 2526450d9..8de33b353 100755 --- a/src/Plot2d/Plot2d_Object.cxx +++ b/src/Plot2d/Plot2d_Object.cxx @@ -30,7 +30,7 @@ Plot2d_Object::Plot2d_Object() myHorTitle( "" ), myVerTitle( "" ), myHorUnits( "" ), myVerUnits( "" ), myName( "" ), - myYAxis( QwtPlot::yLeft ) + myYAxis( QwtPlot::yLeft ), myXAxis( QwtPlot::xBottom ) { } @@ -77,6 +77,15 @@ void Plot2d_Object::updatePlotItem( QwtPlotItem* theItem ) { if ( theItem->rtti() != rtti() ) return; + + if ( theItem->yAxis() != getYAxis() || theItem->xAxis() != getXAxis() ) { + theItem->setAxis( getXAxis(), getYAxis() ); + + QwtPlot* aPlot = theItem->plot(); + theItem->detach(); + theItem->attach( aPlot ); + } + theItem->setTitle( !getName().isEmpty() ? getName() : getVerTitle() ); } /** @@ -328,6 +337,23 @@ QwtPlot::Axis Plot2d_Object::getYAxis() const return myYAxis; } +/*! + Sets object's x axis +*/ +void Plot2d_Object::setXAxis(QwtPlot::Axis theXAxis) +{ + if(theXAxis == QwtPlot::xBottom || theXAxis == QwtPlot::xTop) + myXAxis = theXAxis; +} + +/*! + Gets object's x axis +*/ +QwtPlot::Axis Plot2d_Object::getXAxis() const +{ + return myXAxis; +} + /*! Gets object's minimal abscissa */ diff --git a/src/Plot2d/Plot2d_Object.h b/src/Plot2d/Plot2d_Object.h index 8d116d863..3db5b1b91 100755 --- a/src/Plot2d/Plot2d_Object.h +++ b/src/Plot2d/Plot2d_Object.h @@ -89,6 +89,8 @@ public: void setYAxis( QwtPlot::Axis ); QwtPlot::Axis getYAxis() const; + void setXAxis( QwtPlot::Axis ); + QwtPlot::Axis getXAxis() const; // Protection against QwtObject::drawLines() bug in Qwt 0.4.x: // it crashes if switched to X/Y logarithmic mode, when one or more points have @@ -106,6 +108,7 @@ protected: QString myVerUnits; QString myName; QwtPlot::Axis myYAxis; + QwtPlot::Axis myXAxis; pointList myPoints; }; diff --git a/src/Plot2d/Plot2d_ViewFrame.cxx b/src/Plot2d/Plot2d_ViewFrame.cxx index 1244096e7..b9ee9a259 100755 --- a/src/Plot2d/Plot2d_ViewFrame.cxx +++ b/src/Plot2d/Plot2d_ViewFrame.cxx @@ -241,7 +241,14 @@ void Plot2d_ViewFrame::DisplayAll() */ void Plot2d_ViewFrame::EraseAll() { - myPlot->clear(); + // method clear in version of Qwt5.x detached only Curve or Marker items, + // but we want clear also another items + // myPlot->clear(); + // clear all items from plot view + objectList anObjects; + getObjects( anObjects ); + eraseObjects( anObjects, true ); + myObjects.clear(); myPlot->replot(); } @@ -1860,8 +1867,10 @@ void Plot2d_ViewFrame::updateTitles() ObjectDict::iterator it = myObjects.begin(); QStringList aXTitles; QStringList aYTitles; + QStringList aY2Titles; QStringList aXUnits; QStringList aYUnits; + QStringList aY2Units; QStringList aTables; int i = 0; @@ -1874,13 +1883,22 @@ void Plot2d_ViewFrame::updateTitles() QString xUnits = anObject->getHorUnits().trimmed(); QString yUnits = anObject->getVerUnits().trimmed(); - aYTitles.append( yTitle ); + if ( anObject->getYAxis() == QwtPlot::yLeft ) { + if ( !aYTitles.contains( yTitle ) ) + aYTitles.append( yTitle ); + if ( !aYUnits.contains( yUnits ) ) + aYUnits.append( yUnits ); + } + else { + if ( !aY2Titles.contains( yTitle ) ) + aY2Titles.append( yTitle ); + if ( !aY2Units.contains( yUnits ) ) + aY2Units.append( yUnits ); + } if ( !aXTitles.contains( xTitle ) ) aXTitles.append( xTitle ); if ( !aXUnits.contains( xUnits ) ) aXUnits.append( xUnits ); - if ( !aYUnits.contains( yUnits ) ) - aYUnits.append( yUnits ); QString aName = anObject->getTableTitle(); if( !aName.isEmpty() && !aTables.contains( aName ) ) @@ -1888,16 +1906,20 @@ void Plot2d_ViewFrame::updateTitles() ++i; } // ... and update plot 2d view - QString xUnits, yUnits; + QString xUnits, yUnits, y2Units; if ( aXUnits.count() == 1 && !aXUnits[0].isEmpty() ) xUnits = BRACKETIZE( aXUnits[0] ); if ( aYUnits.count() == 1 && !aYUnits[0].isEmpty()) yUnits = BRACKETIZE( aYUnits[0] ); - QString xTitle, yTitle; + if ( aY2Units.count() == 1 && !aY2Units[0].isEmpty()) + y2Units = BRACKETIZE( aY2Units[0] ); + QString xTitle, yTitle, y2Title; if ( aXTitles.count() == 1 && aXUnits.count() == 1 ) xTitle = aXTitles[0]; if ( aYTitles.count() == 1 ) yTitle = aYTitles[0]; + if ( mySecondY && aY2Titles.count() == 1 ) + y2Title = aY2Titles[0]; if ( !xTitle.isEmpty() && !xUnits.isEmpty() ) xTitle += " "; @@ -1906,6 +1928,8 @@ void Plot2d_ViewFrame::updateTitles() setTitle( myXTitleEnabled, xTitle + xUnits, XTitle, true ); setTitle( myYTitleEnabled, yTitle + yUnits, YTitle, true ); + if ( mySecondY ) + setTitle( myY2TitleEnabled, y2Title + y2Units, Y2Title, true ); setTitle( true, aTables.join("; "), MainTitle, true ); } -- 2.39.2