Salome HOME
Update copyrights 2014.
[modules/gui.git] / src / Plot2d / Plot2d_Histogram.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  File   : Plot2d_Histogram.cxx
23 //  Author : Natalia ERMOLAEVA, Open CASCADE S.A.S. (natalia.donis@opencascade.com)
24
25 #include "Plot2d_Histogram.h"
26 #include "Plot2d_PlotItems.h"
27
28 #include <qwt_plot_curve.h>
29
30 const int MAX_ATTEMPTS = 10;     // max attempts
31
32 /*!
33   Constructor.
34 */
35 Plot2d_Histogram::Plot2d_Histogram()
36 : Plot2d_Object(),
37   myColor( 0, 0, 0 ),
38   myWidth( 0 ),
39   myDefWidth( 0 )
40 {
41 }
42
43 /*!
44   Destructor.
45 */
46 Plot2d_Histogram::~Plot2d_Histogram()
47 {
48 }
49
50 /*!
51   Copy constructor. Makes deep copy of data.
52 */
53 Plot2d_Histogram::Plot2d_Histogram( const Plot2d_Histogram& hist )
54 : Plot2d_Object( hist )
55 {
56   myColor      = hist.myColor;
57   myWidth      = hist.myWidth;
58   myDefWidth   = hist.myDefWidth;
59 }
60
61 /*!
62   operator=. Makes deep copy of data.
63 */
64 Plot2d_Histogram& Plot2d_Histogram::operator=( const Plot2d_Histogram& hist )
65 {
66   Plot2d_Object::operator=(hist);
67   myColor      = hist.myColor;
68   myWidth      = hist.myWidth;
69   myDefWidth   = hist.myDefWidth;
70   return *this;
71 }
72
73 /*!
74   Get typeid for the plot2d histogram class
75 */
76 int Plot2d_Histogram::rtti()
77 {
78   return QwtPlotItem::Rtti_PlotHistogram;
79 }
80
81 /*!
82   Create plot object for the histogram
83 */
84 QwtPlotItem* Plot2d_Histogram::createPlotItem()
85 {
86   Plot2d_HistogramItem* anItem = new Plot2d_HistogramItem();
87   updatePlotItem( anItem );
88   return anItem;
89 }
90
91 /*!
92   Auto fill parameters of object by plot view
93 */
94 void Plot2d_Histogram::autoFill( const QwtPlot* thePlot )
95 {
96   setColor( getNextColor( thePlot ) );
97 }
98
99 /*!
100   Updates histogram fields
101 */
102 void Plot2d_Histogram::updatePlotItem( QwtPlotItem* theItem )
103 {
104   if ( theItem->rtti() != rtti() )
105     return;
106
107   Plot2d_HistogramItem* anItem = dynamic_cast<Plot2d_HistogramItem*>( theItem );
108   if ( !anItem )
109     return;
110
111   Plot2d_Object::updatePlotItem( theItem );
112
113   anItem->setData( getData() );
114   anItem->setLegendPen(getColor());
115   anItem->setSelected(isSelected());
116   anItem->setColor( isSelected() ? Plot2d_Object::selectionColor() : getColor() );
117 }
118
119 /*!
120   Sets data to object
121 */
122 void Plot2d_Histogram::setData( const QList<double>& theXVals,
123                                 const QList<double>& theYVals )
124 {
125   pointList aPoints;
126   int aSize = theXVals.size();
127   for ( int i = 0; i < aSize; i++ )
128     aPoints.append( Plot2d_Point( theXVals[i], theYVals[i] ) );
129   setPointList( aPoints );
130
131   myDefWidth = getMinInterval( theXVals )*(2./3.);
132   myWidth = 0; // myDefWidth // VSR: width should not be automatically reset to myDefWidth
133 }
134
135 /*!
136   Gets data
137 */
138 QwtIntervalData Plot2d_Histogram::getData() const
139 {
140   pointList aPoints = getPointList();
141   int aSize = aPoints.size();
142
143   QwtArray<QwtDoubleInterval> anIntervals( aSize );
144   QwtArray<double> aValues( aSize );
145   double aX;
146   double aWidth = myWidth <= 0 ? myDefWidth : myWidth; // VSR: width is either manually assigned or auto-calculated
147   for ( int i = 0; i < aSize; i++ ) {
148     aX = aPoints[i].x;
149     anIntervals[i] = QwtDoubleInterval( aX - aWidth/2, aX + aWidth/2 );
150     aValues[i] = aPoints[i].y;
151   }
152
153   return QwtIntervalData( anIntervals, aValues );
154 }
155
156 /*!
157   Sets color of histogram
158 */
159 void Plot2d_Histogram::setColor( const QColor& theColor )
160 {
161   myColor = theColor;
162   setAutoAssign( false );
163 }
164
165 /*!
166   Returns color of histogram
167 */
168 QColor Plot2d_Histogram::getColor() const
169 {
170   return myColor;
171 }
172
173 /*!
174   Sets custom width of a histogram bar
175 */
176 void Plot2d_Histogram::setWidth( const double theWidth )
177 {
178   myWidth = theWidth;
179   //setAutoAssign( false ); // VSR: width attribute is not auto-assigned
180 }
181
182 /*!
183   Returns custom or automatic width for a histogram bar
184 */
185 double Plot2d_Histogram::getWidth( const bool isDef ) const
186 {
187   return isDef ? myDefWidth : myWidth;
188 }
189
190 /*!
191   Gets new unique marker for item if possible
192 */
193 QColor Plot2d_Histogram::getNextColor( const QwtPlot* thePlot )
194 {
195   bool bOk = false;
196   int cnt = 0;
197   QColor aColor;
198   while ( !bOk ) {
199     int aRed    = (int)( 256.0 * rand() / RAND_MAX);  // generate random color
200     int aGreen  = (int)( 256.0 * rand() / RAND_MAX);  // ...
201     int aBlue   = (int)( 256.0 * rand() / RAND_MAX);  // ...
202     aColor      = QColor( aRed, aGreen, aBlue );
203     bOk = ( ++cnt == MAX_ATTEMPTS ) || !existColor( thePlot, aColor );
204   }
205   return aColor;
206 }
207
208 /*!
209   Checks if color is already user by other histogram entity
210 */
211 bool Plot2d_Histogram::existColor( const QwtPlot* thePlot, const QColor& theColor )
212 {
213   bool ok = false;
214   
215   QColor bgColor = thePlot->palette().color( QPalette::Background );
216   if ( Plot2d::closeColors( theColor, bgColor ) ) {
217     ok = true;
218   }
219   else {
220     QwtPlotItemList anItems = thePlot->itemList();
221     QwtPlotItemIterator anIt = anItems.begin(), aLast = anItems.end();
222     QwtPlotItem* anItem;
223     for( ; anIt != aLast && !ok; anIt++ ) {
224       anItem = *anIt;
225       if ( !anItem )
226         continue;
227       if ( anItem->rtti() == rtti() ) {
228         Plot2d_HistogramItem* aHItem = dynamic_cast<Plot2d_HistogramItem*>( anItem );
229         ok = aHItem && Plot2d::closeColors( theColor, aHItem->color() );
230       }
231       else if ( anItem->rtti() == QwtPlotItem::Rtti_PlotCurve ) {
232         QwtPlotCurve* aCurve = dynamic_cast<QwtPlotCurve*>( anItem );
233         ok = aCurve && Plot2d::closeColors( theColor, aCurve->pen().color() );
234       }
235     }
236   }
237   return ok;
238 }
239
240 /*!
241   Return min interval from values
242 */
243 double Plot2d_Histogram::getMinInterval( const QList<double>& theVals )
244 {
245   double aValue = -1;
246   int aSize = theVals.size();
247   if ( aSize > 1 ) {
248     aValue = qAbs( theVals[1] - theVals[0] );
249     double aDelta;
250     for ( int i = 2; i < aSize; i++ ) {
251       aDelta = qAbs( theVals[i] - theVals[i-1] );
252       aValue = qMin( aValue, qMax( aDelta, 0. ) );
253     }
254     aValue = aValue/2;
255   }
256   return aValue;
257 }
258