Salome HOME
Updated copyright comment
[modules/gui.git] / src / Plot2d / Plot2d_Histogram.cxx
1 // Copyright (C) 2007-2024  CEA, EDF, 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 QwtIntervalSeriesData Plot2d_Histogram::getData() const
139 {
140   pointList aPoints = getPointList();
141   int aSize = aPoints.size();
142
143   QwtArray<QwtIntervalSample> anIntervals( aSize );
144   double aX;
145   double aWidth = myWidth <= 0 ? myDefWidth : myWidth; // VSR: width is either manually assigned or auto-calculated
146   for ( int i = 0; i < aSize; i++ ) {
147     aX = aPoints[i].x;
148     anIntervals[i] = QwtIntervalSample( aPoints[i].y, aX - aWidth/2, aX + aWidth/2 );
149   }
150
151   return QwtIntervalSeriesData( anIntervals );
152 }
153
154 /*!
155   Sets color of histogram
156 */
157 void Plot2d_Histogram::setColor( const QColor& theColor )
158 {
159   myColor = theColor;
160   setAutoAssign( false );
161 }
162
163 /*!
164   Returns color of histogram
165 */
166 QColor Plot2d_Histogram::getColor() const
167 {
168   return myColor;
169 }
170
171 /*!
172   Sets custom width of a histogram bar
173 */
174 void Plot2d_Histogram::setWidth( const double theWidth )
175 {
176   myWidth = theWidth;
177   //setAutoAssign( false ); // VSR: width attribute is not auto-assigned
178 }
179
180 /*!
181   Returns custom or automatic width for a histogram bar
182 */
183 double Plot2d_Histogram::getWidth( const bool isDef ) const
184 {
185   return isDef ? myDefWidth : myWidth;
186 }
187
188 /*!
189   Gets new unique marker for item if possible
190 */
191 QColor Plot2d_Histogram::getNextColor( const QwtPlot* thePlot )
192 {
193   bool bOk = false;
194   int cnt = 0;
195   QColor aColor;
196   while ( !bOk ) {
197     int aRed    = (int)( 256.0 * rand() / RAND_MAX);  // generate random color
198     int aGreen  = (int)( 256.0 * rand() / RAND_MAX);  // ...
199     int aBlue   = (int)( 256.0 * rand() / RAND_MAX);  // ...
200     aColor      = QColor( aRed, aGreen, aBlue );
201     bOk = ( ++cnt == MAX_ATTEMPTS ) || !existColor( thePlot, aColor );
202   }
203   return aColor;
204 }
205
206 /*!
207   Checks if color is already user by other histogram entity
208 */
209 bool Plot2d_Histogram::existColor( const QwtPlot* thePlot, const QColor& theColor )
210 {
211   bool ok = false;
212   
213   QColor bgColor = thePlot->palette().color( QPalette::Background );
214   if ( Plot2d::closeColors( theColor, bgColor ) ) {
215     ok = true;
216   }
217   else {
218     QwtPlotItemList anItems = thePlot->itemList();
219     QwtPlotItemIterator anIt = anItems.begin(), aLast = anItems.end();
220     QwtPlotItem* anItem;
221     for( ; anIt != aLast && !ok; anIt++ ) {
222       anItem = *anIt;
223       if ( !anItem )
224         continue;
225       if ( anItem->rtti() == rtti() ) {
226         Plot2d_HistogramItem* aHItem = dynamic_cast<Plot2d_HistogramItem*>( anItem );
227         ok = aHItem && Plot2d::closeColors( theColor, aHItem->color() );
228       }
229       else if ( anItem->rtti() == QwtPlotItem::Rtti_PlotCurve ) {
230         QwtPlotCurve* aCurve = dynamic_cast<QwtPlotCurve*>( anItem );
231         ok = aCurve && Plot2d::closeColors( theColor, aCurve->pen().color() );
232       }
233     }
234   }
235   return ok;
236 }
237
238 /*!
239   Return min interval from values
240 */
241 double Plot2d_Histogram::getMinInterval( const QList<double>& theVals )
242 {
243   double aValue = -1;
244   int aSize = theVals.size();
245   if ( aSize > 1 ) {
246     aValue = qAbs( theVals[1] - theVals[0] );
247     double aDelta;
248     for ( int i = 2; i < aSize; i++ ) {
249       aDelta = qAbs( theVals[i] - theVals[i-1] );
250       aValue = qMin( aValue, qMax( aDelta, 0. ) );
251     }
252     aValue = aValue/2;
253   }
254   return aValue;
255 }
256