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 //
46 // CLASS QtFunctionPlot - IMPLEMENTATION
47 //
48 //=============================================================================
49 
50 //== INCLUDES =================================================================
51 
52 #ifdef WITH_QWT
53 
54 #include "QwtFunctionPlot.hh"
55 
56 #include <iostream>
57 #include <algorithm>
58 
59 #include <QPen>
60 
61 #include <QLineEdit>
62 #include <QLabel>
63 #include <QPainter>
64 #include <qwt_curve_fitter.h>
65 #include <qwt_plot_panner.h>
66 #include <qwt_symbol.h>
67 
68 
69 #if QWT_VERSION >= 0x060000
70  #include <qwt_plot_histogram.h>
71 #else
72  #include <qwt_interval_data.h>
73 #endif
74 
75 #include <cfloat>
76 #include <cmath>
77 #include "TextureMath.hh"
78 
79 //== NAMESPACES ===============================================================
80 
81 namespace ACG {
82 
83 //== IMPLEMENTATION ==========================================================
84 
85 
87 QwtFunctionPlot::QwtFunctionPlot(QWidget* _parent) :
88  QDialog( _parent ),
89  Ui::QwtFunctionPlotBase(),
90  plot_zoomer_(0),
91  clampMinMarker_(0),
92  minSymbol_(0),
93  clampMaxMarker_(0),
94  maxSymbol_(0),
95  min_(FLT_MAX),
96  max_(FLT_MIN)
97 {
98  setupUi( this );
99 
100  plot_zoomer_ = new QwtPlotZoomer( qwtPlot->canvas());
101  plot_zoomer_->initKeyPattern();
102  connect(zoomInButton, SIGNAL( clicked() ), this,SLOT( zoomIn() ) );
103  connect(zoomOutButton,SIGNAL( clicked() ), this,SLOT( zoomOut() ) );
104  connect(clampButton, SIGNAL( clicked() ), this,SLOT( clamp() ) );
105 
106  QwtPlotPanner *panner = new QwtPlotPanner( qwtPlot->canvas() );
107  panner->setMouseButton( Qt::MidButton );
108 
109  // delete widget on close
110  setAttribute(Qt::WA_DeleteOnClose, true);
111 
112 #if QWT_VERSION >= 0x060000
113  histogram_ = new Histogram();
114 #else
115  histogram_ = new HistogramItem();
116 #endif
117 
118  image_ = 0;
119 }
120 
121 //------------------------------------------------------------------------------
122 
123 void QwtFunctionPlot::setFunction( std::vector<double>& _values)
124 {
125  values_ = _values;
126 
127  //get min/max values
128  min_ = FLT_MAX;
129  max_ = -FLT_MAX;
130 
131  for ( uint i=0; i < values_.size(); i++){
132  min_ = std::min(min_, values_[i] );
133  max_ = std::max(max_, values_[i] );
134  }
135 
136 }
137 
138 //------------------------------------------------------------------------------
139 
140 void QwtFunctionPlot::setParameters(const TexParameters& _parameters)
141 {
142  parameters_ = _parameters;
143 }
144 
145 void QwtFunctionPlot::setParameters(
146  bool _repeat,
147  double _repeatMax,
148  bool _clamp,
149  double _clampMin,
150  double _clampMax,
151  bool _center,
152  bool _absolute,
153  bool _scale)
154 {
155 
156  parameters_.repeat = _repeat;
157  parameters_.repeatMax = _repeatMax;
158  parameters_.clamp = _clamp;
159  parameters_.clampMin = _clampMin;
160  parameters_.clampMax = _clampMax;
161  parameters_.center = _center;
162  parameters_.abs = _absolute;
163  parameters_.scale = _scale;
164 }
165 
166 
167 //------------------------------------------------------------------------------
168 
169 void QwtFunctionPlot::setImage(QImage* _image)
170 {
171  image_ = _image;
172 }
173 
174 //------------------------------------------------------------------------------
175 
176 void QwtFunctionPlot::zoomIn()
177 {
178  emit plot_zoomer_->zoom(1);
179 }
180 
181 //------------------------------------------------------------------------------
182 
183 void QwtFunctionPlot::zoomOut()
184 {
185  emit plot_zoomer_->zoom(-1);
186 }
187 
188 //------------------------------------------------------------------------------
189 
190 void QwtFunctionPlot::clamp()
191 {
192  QRectF clamped = plot_zoomer_->zoomRect();
193  clamped.setLeft( min_ );
194  clamped.setRight( max_ );
195  emit plot_zoomer_->zoom(clamped);
196 }
197 
198 //------------------------------------------------------------------------------
199 
200 void QwtFunctionPlot::replot()
201 {
202  //create intervals
203  const int intervalCount = 100;
204 
205 #if QWT_VERSION >= 0x060000
206  QVector<QwtIntervalSample> intervals(intervalCount);
207 #else
208  QwtArray<QwtDoubleInterval> intervals(intervalCount);
209  QwtArray<double> count(intervalCount);
210 #endif
211  std::vector< QColor > colors;
212 
213  double pos = min_;
214  double width = ( max_ - min_ ) / intervalCount;
215 
216  QColor lastColor = Qt::black;
217 
218  TextureMath convert(parameters_,min_,max_);
219 
220  for ( int i = 0; i < (int)intervals.size(); i++ )
221  {
222 
223 #if QWT_VERSION >= 0x060000
224  intervals[i] = QwtIntervalSample(0.0,pos, pos + width);
225 #else
226  intervals[i] = QwtDoubleInterval(pos, pos + width);
227 #endif
228  pos += width;
229 
230  //compute a color for the given interval
231  if (image_ != 0){
232 
233  const double intervalCenter = pos + (width/2.0);
234 
235  const double value = convert.transform(intervalCenter);
236  int val = int( value * ( image_->width() - 1) );
237 
238  val = val % image_->width(); // Simulate If texture is repeated, we have to make sure, we stay inside of the image
239  colors.push_back( QColor( image_->pixel(val, 0) ) );
240  lastColor = colors.back();
241  }
242  }
243 
244  //sort values into intervals
245  for ( uint i=0; i < values_.size(); i++)
246  for ( int j = 0; j < (int)intervals.size(); j++ )
247 #if QWT_VERSION >= 0x060000
248  if ( intervals[j].interval.contains( values_[i] ) )
249  intervals[j].value++;
250 #else
251  if ( intervals[j].contains( values_[i] ) )
252  count[j]++;
253 #endif
254 
255  //get max Count for scaling the y-axis
256  double maxCount = 0;
257 
258  for ( int i = 0; i < (int)intervals.size(); i++ )
259 #if QWT_VERSION >= 0x060000
260  maxCount = std::max(maxCount, intervals[i].value);
261 #else
262  maxCount = std::max(maxCount, count[i]);
263 #endif
264 
265 
266 #if QWT_VERSION >= 0x060000
267  QwtIntervalSeriesData* data = new QwtIntervalSeriesData(intervals);
268  histogram_->setData(data);
269 #else
270  histogram_->setData(QwtIntervalData(intervals, count));
271 #endif
272  histogram_->setColors(colors);
273  histogram_->attach(qwtPlot);
274 
275  qwtPlot->setAxisScale(QwtPlot::yLeft, 0.0, maxCount);
276  qwtPlot->setAxisScale(QwtPlot::xBottom, min_, max_);
277 
278  qwtPlot->setAxisTitle(QwtPlot::yLeft, "count" );
279  qwtPlot->setAxisTitle(QwtPlot::xBottom, "values" );
280 
281  //define this scaling as the zoomBase
282  plot_zoomer_->setZoomBase();
283 
284  // Mark the clamp values in the histogramm
285  if ( parameters_.clamp ) {
286  if ( ! clampMinMarker_ ) {
287  clampMinMarker_ = new QwtPlotMarker();
288  minSymbol_ = new QwtSymbol(QwtSymbol::VLine);
289  minSymbol_->setColor(QColor(255,0,0));
290  minSymbol_->setSize(200,1000);
291  QPen pen = minSymbol_->pen();
292  pen.setWidth(3);
293  minSymbol_->setPen(pen);
294  clampMinMarker_->setSymbol(minSymbol_);
295  clampMinMarker_->attach(qwtPlot);
296  }
297 
298  // Draw at left boundary if less than the minimal value we get from the function
299  if ( parameters_.clampMin < min_ )
300  clampMinMarker_->setXValue(min_);
301  else
302  clampMinMarker_->setXValue(parameters_.clampMin);
303 
304 
305 
306  clampMinMarker_->show();
307 
308  if ( ! clampMaxMarker_ ) {
309  clampMaxMarker_ = new QwtPlotMarker();
310  maxSymbol_ = new QwtSymbol(QwtSymbol::VLine);
311  maxSymbol_->setColor(QColor(0,255,0));
312  maxSymbol_->setSize(200,1000);
313  QPen pen = maxSymbol_->pen();
314  pen.setWidth(3);
315  maxSymbol_->setPen(pen);
316  clampMaxMarker_->setSymbol(maxSymbol_);
317  clampMaxMarker_->attach(qwtPlot);
318  }
319 
320  // Draw at right boundary if greater than the maximal value we get from the function
321  if ( parameters_.clampMax < max_ )
322  clampMaxMarker_->setXValue(parameters_.clampMax);
323  else
324  clampMaxMarker_->setXValue(max_);
325 
326  clampMaxMarker_->show();
327 
328  } else {
329  if ( clampMinMarker_ )
330  clampMinMarker_->hide();
331 
332  if ( clampMaxMarker_ )
333  clampMaxMarker_->hide();
334  }
335 
336  // an plot it
337  qwtPlot->replot();
338 }
339 
340 
341 
342 
343 
344 //=============================================================================
345 } // namespace db
346 //=============================================================================
347 
348 #endif // WITH_QWT
Histogram plotting widget.
Namespace providing different geometric functions concerning angles.
Histogram plot.