Developer Documentation
QwtFunctionPlot.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 
43 //=============================================================================
44 //
45 // CLASS QtFunctionPlot - IMPLEMENTATION
46 //
47 //=============================================================================
48 
49 //== INCLUDES =================================================================
50 
51 #ifdef WITH_QWT
52 
53 #include "QwtFunctionPlot.hh"
54 
55 #include <iostream>
56 #include <algorithm>
57 
58 #include <QPen>
59 
60 #include <QLineEdit>
61 #include <QLabel>
62 #include <QPainter>
63 #include <qwt_curve_fitter.h>
64 #include <qwt_plot_panner.h>
65 #include <qwt_symbol.h>
66 #include <qwt_plot_histogram.h>
67 
68 #include <ACG/Utils/ColorCoder.hh>
69 
70 
71 #include <cfloat>
72 #include <cmath>
73 
74 //== NAMESPACES ===============================================================
75 
76 //== IMPLEMENTATION ==========================================================
77 
78 
80 QwtFunctionPlot::QwtFunctionPlot(QWidget* _parent) :
81  QDialog( _parent ),
82  Ui::QwtFunctionPlotBase(),
83  plot_zoomer_(0),
84  clampMinMarker_(0),
85  minSymbol_(0),
86  clampMaxMarker_(0),
87  maxSymbol_(0),
88  min_(FLT_MAX),
89  max_(FLT_MIN)
90 {
91  setupUi( this );
92 
93  qwtPlot->setAxisTitle(QwtPlot::yLeft, "count" );
94 
95  plot_zoomer_ = new QwtPlotZoomer( qwtPlot->canvas());
96  plot_zoomer_->initKeyPattern();
97 
98  QwtPlotPanner *panner = new QwtPlotPanner( qwtPlot->canvas() );
99  panner->setMouseButton( Qt::MidButton );
100 
101  // delete widget on close
102  setAttribute(Qt::WA_DeleteOnClose, true);
103 
104  histogram_ = new Histogram();
105 }
106 
107 //------------------------------------------------------------------------------
108 
109 void QwtFunctionPlot::setFunction(const std::vector<double>& _values)
110 {
111  values_ = _values;
112 }
113 
114 //------------------------------------------------------------------------------
115 
116 void QwtFunctionPlot::replot()
117 {
118  //create intervals
119  const int intervalCount = 100;
120 
121  QVector<QwtIntervalSample> intervals(intervalCount);
122  std::vector< QColor > colors;
123 
124  double realMin = FLT_MAX;
125  double realMax = -FLT_MAX;
126 
127  for ( unsigned int i=0; i < values_.size(); i++) {
128  realMin = std::min(realMin,values_[i]);
129  realMax = std::max(realMax,values_[i]);
130  }
131 
132  double pos = realMin;
133  double width = ( realMax - realMin ) / intervalCount;
134 
135  QColor lastColor = Qt::black;
136 
137  ACG::ColorCoder cCoder(std::max(min_,realMin),std::min(max_,realMax));
138 
139  for ( int i = 0; i < (int)intervals.size(); i++ )
140  {
141 
142  intervals[i] = QwtIntervalSample(0.0,pos, pos + width);
143  pos += width;
144 
145  //compute a color for the given interval
146  const double intervalCenter = pos + (width/2.0);
147 
148  colors.push_back( cCoder.color_qcolor(intervalCenter) );
149  lastColor = colors.back();
150  }
151 
152  // sort values into intervals
153  // Could be more efficient when we calculate the correct interval based on the above loop directly
154  for ( uint i=0; i < values_.size(); i++)
155  for ( int j = 0; j < (int)intervals.size(); j++ )
156  if ( intervals[j].interval.contains( values_[i] ) ) {
157  intervals[j].value++;
158  break;
159  }
160 
161  //get max Count for scaling the y-axis
162  double maxCount = 0;
163 
164  for ( int i = 0; i < (int)intervals.size(); i++ )
165  maxCount = std::max(maxCount, intervals[i].value);
166 
167 
168  QwtIntervalSeriesData* data = new QwtIntervalSeriesData(intervals);
169  histogram_->setData(data);
170  histogram_->setColors(colors);
171  histogram_->attach(qwtPlot);
172 
173  qwtPlot->setAxisScale(QwtPlot::yLeft, 0.0, maxCount);
174  qwtPlot->setAxisScale(QwtPlot::xBottom, realMin, realMax);
175 
176  //define this scaling as the zoomBase
177  plot_zoomer_->setZoomBase();
178 
179  //Mark the clamp values in the histogram.
180  if ( min_ > realMin ) {
181  if ( ! clampMinMarker_ ) {
182  clampMinMarker_ = new QwtPlotMarker();
183  minSymbol_ = new QwtSymbol(QwtSymbol::VLine);
184  minSymbol_->setColor(cCoder.color_qcolor(std::max(min_,realMin)));
185  minSymbol_->setSize(200,1000);
186  QPen pen = minSymbol_->pen();
187  pen.setWidth(3);
188  minSymbol_->setPen(pen);
189  clampMinMarker_->setSymbol(minSymbol_);
190  clampMinMarker_->attach(qwtPlot);
191  clampMinMarker_->show();
192  }
193 
194  // Draw at right boundary if greater than the maximal value we get from the function
195  clampMinMarker_->setXValue(std::max(min_,realMin));
196 
197  } else {
198  if ( clampMinMarker_ ) {
199  clampMinMarker_->detach();
200  delete clampMinMarker_;
201  clampMinMarker_ = 0;
202  }
203  }
204 
205  //Mark the clamp values in the histogram.
206  if ( max_ < realMax ) {
207  if ( ! clampMaxMarker_ ) {
208  clampMaxMarker_ = new QwtPlotMarker();
209  maxSymbol_ = new QwtSymbol(QwtSymbol::VLine);
210  maxSymbol_->setColor(cCoder.color_qcolor(std::min(max_,realMax)));
211  maxSymbol_->setSize(200,1000);
212  QPen pen = maxSymbol_->pen();
213  pen.setWidth(3);
214  maxSymbol_->setPen(pen);
215  clampMaxMarker_->setSymbol(maxSymbol_);
216  clampMaxMarker_->attach(qwtPlot);
217  clampMaxMarker_->show();
218  }
219 
220  // Draw at right boundary if greater than the maximal value we get from the function
221  clampMaxMarker_->setXValue(std::min(max_,realMax));
222 
223  } else {
224  if ( clampMaxMarker_ ) {
225  clampMaxMarker_->detach();
226  delete clampMaxMarker_;
227  clampMaxMarker_ = 0;
228  }
229  }
230 
231  // an plot it
232  qwtPlot->replot();
233 }
234 
235 void QwtFunctionPlot::setMinMax(double _min, double _max) {
236  min_ = _min;
237  max_ = _max;
238 }
239 
240 
241 
242 //=============================================================================
243 //=============================================================================
244 
245 #endif // WITH_QWT
Histogram plot.
Class for generating nice colors for doubles.
Definition: ColorCoder.hh:68