HistogramChart.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file HistogramChart.cpp
22 
23  \brief A class to represent a histogram chart.
24 */
25 
26 //Terralib
27 #include "../../../dataaccess/dataset/ObjectId.h"
28 #include "../../../dataaccess/dataset/ObjectIdSet.h"
29 #include "../../../dataaccess/utils/Utils.h"
30 #include "../../../qt/widgets/se/Utils.h"
31 #include "../../../se/Stroke.h"
32 #include "Enums.h"
33 #include "Histogram.h"
34 #include "HistogramChart.h"
35 #include "HistogramStyle.h"
36 #include "StringScaleDraw.h"
37 #include "Utils.h"
38 
39 
40 //QT
41 #include <qbrush.h>
42 #include <qpen.h>
43 
44 //QWT
45 #include <qwt_column_symbol.h>
46 #include <qwt_plot.h>
47 
48 //STL
49 #include <limits>
50 
52  Histogram* histogram, te::qt::widgets::HistogramStyle* style)
53  :
54 
55  m_histogram(histogram),
56  m_histogramStyle(style)
57 {
58  if(!m_histogramStyle)
59  {
61  QPen barPen;
62  QBrush barBrush;
63 
66  barBrush.setStyle(Qt::SolidPattern);
67 
68  setPen(barPen);
69  setBrush(barBrush);
70  }
71 
72  setData();
73 
75  m_selection->setStyle(QwtPlotHistogram::Columns);
76 
77  //The default selection color is green
78  m_selection->setBrush(QColor("#00FF00"));
79  m_selection->attach(plot());
80 
81 }
82 
84 {
85  //Vector that will be populated by the histogram's data
86  QVector<QwtIntervalSample> samples;
90  {
91  std::map<double, unsigned int> values;
92  values = m_histogram->getValues();
93 
94  std::map<double, unsigned int>::const_iterator it;
95  it = values.begin();
96 
97  std::map<int, unsigned int> vmap;
98 
99  int i = 0;
100 
101  double ini = m_histogram->getMinValue();
102 
103  double vx = ini + m_histogram->getInterval();
104 
105  while(vx <= values.rbegin()->first)
106  {
107  vmap[i] = 0;
108  if(fabs(vx) < 0.000000000001)
109  vx = 0.;
110  while(it != values.end())
111  {
112  if(it->first >= ini && it->first < vx)
113  vmap[i] += it->second;
114  else
115  break;
116  ++it;
117  }
118 
119  QwtInterval qinterval(ini, vx);
120  qinterval.setBorderFlags(QwtInterval::ExcludeMaximum);
121  samples.push_back(QwtIntervalSample(vmap[i], qinterval));
122 
123  ini = vx;
124  vx += m_histogram->getInterval();
125  ++i;
126  }
127  setSamples(samples);
128  }
129 
131  {
132  std::map<std::string, unsigned int> values;
133  values = m_histogram->getStringValues();
134 
135  std::map<std::string, unsigned int>::iterator it;
136  it = values.begin();
137 
139  QVector<QwtIntervalSample> samples((int)values.size());
140  double LabelInterval = 0.0;
141 
142  while (it != values.end())
143  {
144  QwtInterval qwtInterval(LabelInterval, LabelInterval+1);
145  qwtInterval.setBorderFlags(QwtInterval::ExcludeMaximum);
146  samples[LabelInterval] = QwtIntervalSample(it->second, qwtInterval);
147  LabelInterval++;
148  it++;
149  }
150  setSamples(samples);
151  }
152  else
153  {
154  std::map<double, unsigned int> values;
155  std::map<double, unsigned int>::const_iterator it;
156  values = m_histogram->getValues();
157  it = values.begin();
158 
159  //Checking if there is a defined interval, and if it is possible to define one
160  if (values.size() > 0 && m_histogram->getInterval() == std::numeric_limits<double>::max())
161  {
162  //Attempting to define an interval
163  const double min = values.begin()->first;
164  const double max = values.rbegin()->first;
165  m_histogram->setInterval((max - min) / ((double)(values.size() - 1)));
166  }
167 
168  // The raster's interval was defined
169  if (m_histogram->getInterval() != std::numeric_limits<double>::max())
170  {
171  double ini = m_histogram->getMinValue();
172  double vx = ini + m_histogram->getInterval();
173 
174  while (it != values.end())
175  {
176  QwtInterval qwtInterval(ini, vx);
177  samples.push_back(QwtIntervalSample(it->second, qwtInterval));
178  it++;
179  ini = vx;
180  vx += m_histogram->getInterval();
181  }
182  }
183  else
184  {
185  while (it != values.end())
186  {
187  double interval = it->first;
188  QwtInterval qwtInterval(interval, interval + 1);
189  samples.push_back(QwtIntervalSample(it->second, qwtInterval));
190  it++;
191  }
192  }
193 
194  QPen blankPen = QPen(Qt::transparent);
195  setPen(blankPen);
196 
197  te::se::Stroke* blankStroke = new te::se::Stroke();
198  blankStroke->setOpacity(QString::number(0, 'g', 2).toUtf8().data());
199  m_histogramStyle->setStroke(blankStroke);
200  setSamples(samples);
201  }
202 }
203 
205 {
206  delete m_histogram;
207  delete m_histogramStyle;
208  delete m_selection;
209 }
210 
212 {
214 }
215 
217 {
218  return m_histogramScaleDraw;
219 }
220 
222 {
223  delete m_histogramScaleDraw;
224  m_histogramScaleDraw = newScaleDraw;
225  plot()->setAxisScaleDraw(QwtPlot::xBottom, m_histogramScaleDraw);
226 }
227 
229 {
231  {
232  plot->setAxisScaleDraw(QwtPlot::xBottom, m_histogramScaleDraw);
233  plot->axisScaleDraw(QwtPlot::xBottom)->setLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter);
234  plot->axisScaleDraw(QwtPlot::xBottom)->setLabelRotation(-60);
235  }
236 
237  QwtPlotHistogram::attach(plot);
238 }
239 
241 {
242  return m_histogram;
243 }
244 
246 {
247  delete m_histogram;
248  m_histogram = newHistogram;
249 }
250 
252 {
253  return m_histogramStyle->clone();
254 }
255 
257 {
258  delete m_histogramStyle;
259  m_histogramStyle = newStyle;
260 
261  //The pen and brush that will be used
262  QPen barPen;
263  QBrush barBrush;
264 
265  //Configuring the pen and brush based on the current style
268  barBrush.setStyle(Qt::SolidPattern);
269 
270  //Updating the chart's pen and brush.
271  setPen(barPen);
272  setBrush(barBrush);
273 }
274 
276 {
277  //Removing the previous selection, if there was any.
278  m_selection->detach();
279 
280  std::set<te::da::ObjectId*, te::common::LessCmp<te::da::ObjectId*> >::const_iterator itObjSet;
281  QwtSeriesData<QwtIntervalSample>* values = data();
282 
283  //Acquiring all selected intervals:
284 
288  {
289  std::map<double, unsigned int> highlightedIntervals;
290  std::set<std::string> highlightedPkeys;
291 
292  //Acquiring the slected intervals
293  for(itObjSet = oids->begin(); itObjSet != oids->end(); ++itObjSet)
294  {
295  const te::dt::Double* data = static_cast< const te::dt::Double*>(m_histogram->find((*itObjSet)));
296  if(data)
297  {
298  double interval = data->getValue();
299  highlightedIntervals.insert(std::make_pair(interval, 0));
300  }
301  }
302 
303  //Acquiring the name of the base dataset and how many of it's properties are included in it's primary key
304  std::pair<std::string, int> dsProps;
305  te::da::GetOIDDatasetProps(dataType, dsProps);
306 
307  //Acquiring the selected values' frequency
308  for(itObjSet = oids->begin(); itObjSet != oids->end(); ++itObjSet)
309  {
310  //Acquiring the value of the base primaryKey on the current objectId;
311  std::string pKey = te::da::getBasePkey((*itObjSet),dsProps);
313  {
314  if(highlightedPkeys.insert(pKey).second)
315  {
316  const te::dt::Double* data = static_cast< const te::dt::Double*>(m_histogram->find((*itObjSet)));
317  if(data)
318  {
319  double interval = data->getValue();
320  ++highlightedIntervals.at(interval);
321  }
322  }
323  }
324  else
325  {
326  const te::dt::Double* data = static_cast< const te::dt::Double*>(m_histogram->find((*itObjSet)));
327  if(data)
328  {
329  double interval = data->getValue();
330  ++highlightedIntervals.at(interval);
331  }
332  }
333  }
334 
335  QVector<QwtIntervalSample> highlightedSamples((int)highlightedIntervals.size());
336 
337  //Acquiring all selected samples:
338  for(size_t i = 0; i < values->size(); ++i)
339  {
340  for (std::map<double, unsigned int>::iterator it = highlightedIntervals.begin(); it != highlightedIntervals.end(); ++it)
341  {
342  //Comparing with the minimum value. Our histogram is created based on the exclude maximum policy.
343  if(values->sample(i).interval.minValue() == it->first)
344  {
345  QwtInterval qwtInterval(values->sample(i).interval.minValue(), values->sample(i).interval.maxValue());
346  highlightedSamples.push_back(QwtIntervalSample(it->second, qwtInterval));
347  }
348  }
349  }
350  m_selection->setData(new QwtIntervalSeriesData(highlightedSamples));
351  }
352 
354  {
355 
356  //A vector that will contain the selected strings
357  std::map<std::string, unsigned int> highlightedIntervals;
358 
359  //Acquiring the slected intervals
360  for(itObjSet = oids->begin(); itObjSet != oids->end(); ++itObjSet)
361  {
362  const te::dt::String* data = static_cast<const te::dt::String*>(m_histogram->find((*itObjSet)));
363  if (data)
364  {
365  std::string interval = data->getValue();
366  highlightedIntervals.insert(std::make_pair(interval, 0));
367  }
368  }
369 
370  //Acquiring the selected values' frequency
371  for(itObjSet = oids->begin(); itObjSet != oids->end(); ++itObjSet)
372  {
373  std::string interval = m_histogram->find((*itObjSet))->toString();
374  if(m_histogram->getStringValues().at(interval) > highlightedIntervals.at(interval))
375  ++highlightedIntervals.at(interval);
376  }
377 
378  //A vector containing that will be populated with the samples that match the selected strings
379  QVector<QwtIntervalSample> highlightedSamples((int)highlightedIntervals.size());
380 
381  //Acquiring all selected samples:
382  for(size_t i = 0; i < values->size(); ++i)
383  {
384  for (std::map<std::string, unsigned int>::iterator it = highlightedIntervals.begin(); it != highlightedIntervals.end(); ++it)
385  {
386  //Comparing label by label.
387  if(m_histogramScaleDraw->label(i).text().toUtf8().data() == it->first)
388  {
389  QwtInterval qwtInterval(values->sample(i).interval.minValue(), values->sample(i).interval.maxValue());
390  highlightedSamples.push_back(QwtIntervalSample(it->second, qwtInterval));
391  }
392  }
393  }
394  m_selection->setData(new QwtIntervalSeriesData(highlightedSamples));
395  }
396 
397  m_selection->attach(plot());
398  plot()->replot();
399 }
400 
402 {
403  QwtSeriesData<QwtIntervalSample>* values = data();
404 
406  {
407  std::unique_ptr<te::dt::String> data(new te::dt::String(""));
408  for(size_t i = 0; i < values->size(); ++i)
409  {
410  if(values->sample(i).interval.minValue() < point.rx() && values->sample(i).interval.maxValue() > point.rx() && values->sample(i).value > point.ry())
411  data.reset(new te::dt::String(m_histogramScaleDraw->label(i).text().toUtf8().data()));
412  }
413 
414  return m_histogram->find(data.get());
415  }
416  else
417  {
418  std::unique_ptr<te::dt::Double> data(new te::dt::Double(std::numeric_limits<double>::max()));
419 
420  for(size_t i = 0; i < values->size(); ++i)
421  {
422  if(values->sample(i).interval.minValue() < point.rx() && values->sample(i).interval.maxValue() > point.rx() && values->sample(i).value > point.ry())
423  data.reset(new te::dt::Double(values->sample(i).interval.minValue()));
424  }
425 
426  return m_histogram->find(data.get());
427  }
428 }
429 
431 {
432  QwtSeriesData<QwtIntervalSample>* values = data();
433  std::vector<te::dt::AbstractData*> selected;
434 
436  {
437  for(size_t i = 0; i < values->size(); ++i)
438  {
439  QwtInterval temp(rect.x(), (rect.x() + rect.width()));
440  int frequency = values->sample(i).value;
441 
442  if((values->sample(i).interval.contains(rect.x()) || values->sample(i).interval.intersects(temp))
443  && frequency > rect.y())
444  selected.push_back(new te::dt::String(m_histogramScaleDraw->label(i).text().toUtf8().data()));
445  }
446  }
447  else
448  {
449  for(size_t i = 0; i < values->size(); ++i)
450  {
451  QwtInterval temp(rect.x(), (rect.x() + rect.width()));
452  int frequency = values->sample(i).value;
453 
454  if((values->sample(i).interval.contains(rect.x()) || values->sample(i).interval.intersects(temp))
455  && frequency > rect.y())
456  selected.push_back(new te::dt::Double(values->sample(i).interval.minValue()));
457  }
458  }
459 
460  return m_histogram->find(selected);
461 }
462 
464 {
465  m_selection->setBrush(selColor);
466 }
StringScaleDraw * m_histogramScaleDraw
Scale draw that defines how a label will be displayed on this chart.
te::se::Fill * getFill()
Returns a pointer to the histogram bar&#39;s fill.
HistogramChart(Histogram *data, te::qt::widgets::HistogramStyle *style=0)
Constructor.
A class that models the description of a dataset.
Definition: DataSetType.h:72
void attach(QwtPlot *plot)
It atttaches a QwtPlot to this Cahrt.
virtual int rtti() const
Returns the chart&#39;s type.
void highlight(const te::da::ObjectIdSet *oids, te::da::DataSetType *dataType)
Highlights the objects identified by oids.
Histogram * m_histogram
The histogram that will be shown on this chart.
void setHistogramStyle(te::qt::widgets::HistogramStyle *newStyle)
It sets the chart&#39;s style.
T getValue() const
It returns the associated value.
Definition: SimpleData.h:139
A class to represent a Histogram.
Definition: Histogram.h:56
A class to represent a set of labels to be used on a histogram&#39;s chart.
te::se::Stroke * getStroke()
Returns a pointer to the histogram bar&#39;s stroke.
TEDATAACCESSEXPORT void GetOIDDatasetProps(const DataSetType *type, std::pair< std::string, int > &dsProps)
void setScaleDraw(StringScaleDraw *newScaleDraw)
It sets the chart&#39;s scale draw.
void setHistogram(te::qt::widgets::Histogram *newHistogram)
It sets the chart&#39;s histogram.
A class used to define the style of a histogram&#39;s chart.
A class to represent a histogram.
TEQTWIDGETSEXPORT void Config(QPen &pen, const te::se::Stroke *stroke)
It configs the given pen based on Symbology Enconding Stroke element.
virtual QwtText label(double value) const
It returns the label at the given index.
void setOpacity(const std::string &opacity)
Definition: Stroke.cpp:93
HistogramStyle * clone()
Returns a pointer to a clone of this HistogramStyle.
te::qt::widgets::HistogramStyle * m_histogramStyle
The histogram&#39;s style as displayed by this widget.
te::qt::widgets::HistogramStyle * getHistogramStyle()
Returns a clone of the pointer to the histogram&#39;s style.
This class represents a set of unique ids created in the same context. i.e. from the same data set...
Definition: ObjectIdSet.h:55
QwtPlotHistogram * m_selection
The PlotItems to be highlighted when a selection occurs;.
te::qt::widgets::Histogram * getHistogram()
It returns the chart&#39;s histogram.
std::map< std::string, unsigned int > getStringValues()
It returns the map containing the histogram String values. The key is a unique string that represents...
Definition: Histogram.cpp:86
A class to represent a histogram chart.
double & getMinValue()
It returns the histogram&#39;s minimum value. Will be invalid if the histogram was created based on strin...
Definition: Histogram.cpp:95
void setInterval(double new_Interval)
It sets the histogram&#39;s interval.
Definition: Histogram.cpp:110
Utility functions for the data access module.
void setSelectionColor(QColor selColor)
color used to hgihlight selected objects on this chart.
std::map< double, unsigned int > getValues()
It returns the map containing the histogram values. The key is the minimum values of the histogram&#39;s ...
Definition: Histogram.cpp:62
std::set< ObjectId *, te::common::LessCmp< ObjectId * > >::const_iterator end() const
Returns an iterator for the object ids in container.
A Stroke specifies the appearance of a linear geometry.
Definition: Stroke.h:67
TEDATAACCESSEXPORT std::string getBasePkey(te::da::ObjectId *oid, std::pair< std::string, int > &dsProps)
std::set< std::string > & getStringInterval()
It returns the histogram&#39;s string set of intervals. Will be invalid if the histogram was created base...
Definition: Histogram.cpp:115
bool isSummarized()
It returns a boolean that holds whether the histogram has been created from summarized values or not...
Definition: Histogram.cpp:52
A template for atomic data types (integers, floats, strings and others).
Definition: SimpleData.h:59
double & getInterval()
It returns the histogram&#39;s interval. Will be invalid if the histogram was created based on string int...
Definition: Histogram.cpp:105
int & getType()
It returns the histogram&#39;s type.
Definition: Histogram.cpp:42
std::set< ObjectId *, te::common::LessCmp< ObjectId * > >::const_iterator begin() const
Returns an iterator for the object ids in container.
StringScaleDraw * getScaleDraw()
It returns the chart&#39;s scale draw.
void setStroke(te::se::Stroke *newStroke)
It sets the histogram bar&#39;s stroke.
te::da::ObjectIdSet * find(te::dt::AbstractData *interval)
It returns an ObjectIdSet containing all the object Ids associeted with the given interval...
Definition: Histogram.cpp:165