GroupingAlgorithms.h
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 GroupingAlgorithms.h
22 
23  \brief This file contains functions containing the algorithms for grouping values.
24 */
25 
26 #ifndef __TERRALIB_MAPTOOLS_INTERNAL_GROUPINGALGORITHMS_H
27 #define __TERRALIB_MAPTOOLS_INTERNAL_GROUPINGALGORITHMS_H
28 
29 // TerraLib
30 #include "Config.h"
31 #include "../common/StringUtils.h"
32 #include "../maptools/GroupingItem.h"
33 
34 // STL
35 #include <string>
36 #include <vector>
37 
38 #include <math.h>
39 #include <stdlib.h>
40 
41 
42 #ifndef MIN
43 #define MIN(a,b) ( (a<b) ? a : b ) //!< Macro that returns min between two values
44 #endif
45 
46 #ifndef MAX
47 #define MAX(a,b) ( (a>b) ? a : b ) //!< Macro that returns max between two values
48 #endif
49 
50 
51 namespace te
52 {
53  namespace map
54  {
55  /*!
56  \brief It groups the values using the unique value algorithm.
57 
58  \param inputValues The data to be grouped by unique values.
59  \param dataType The data type of the values.
60  \param legend The container of legend items where the groups will be placed.
61  \precision The precision to be used in the conversion of the values.
62 
63  \output The groups will be stored in the container of legend items.
64  */
65  TEMAPEXPORT void GroupingByUniqueValues(std::vector<std::string>& inputValues, int dataType,
66  std::vector<te::map::GroupingItem*>& legend, int precision);
67 
68  /*!
69  \brief It adjusts a value to the precision specified
70 
71  \param value The value to be adjusted.
72  \param precision The precision the given value must be adjusted to.
73  \param reduce Flag indicating if the value must be added or subtracted to the value represented by the precision.
74 
75  \output The value adjusted to the precision specified.
76  */
77  TEMAPEXPORT double AdjustToPrecision(double val, int precision, bool reduce = false);
78 
79  /*!
80  \brief It groups the values defined by a range of iterators using the equal steps algorithm.
81 
82  \param begin The iterator associated to the first element value.
83  \param end The iterator associated to the last element value.
84  \param nSteps The number of steps.
85  \param legend The container of legend items.
86  \param precision The precision to be used in the conversion of the values.
87  \param countElements The flag indicating if the counting of elements must be done.
88 
89  \output The groups will be stored in the container of legend items.
90  */
91  template<class iterator>
92  void GroupingByEqualSteps(iterator begin, iterator end, int nSteps, std::vector<te::map::GroupingItem*>& legend,
93  int precision = 0, bool countElements = true)
94  {
95  double min = std::numeric_limits<double>::max();
96  double max = -std::numeric_limits<double>::max();
97 
98  iterator it = begin;
99 
100  while(it < end)
101  {
102  min = MIN(min, *it);
103  max = MAX(max, *it);
104  ++it;
105  }
106 
107  double slice = (max - min)/double(nSteps);
108 
109  for(int i = 0; i < nSteps; ++i)
110  {
112  legendItem->setLowerLimit(te::common::Convert2String(min + double(i) * slice, precision));
113  legendItem->setUpperLimit(te::common::Convert2String(min + double(i+1) * slice, precision));
114  legend.push_back(legendItem);
115  }
116 
117  min = te::map::AdjustToPrecision(min, precision, true);
118  legend[0]->setLowerLimit(te::common::Convert2String(min, precision));
119  max = te::map::AdjustToPrecision(max, precision, false);
120  legend[nSteps-1]->setUpperLimit(te::common::Convert2String(max, precision));
121 
122  // Set the number of elements for each slice
123  if (countElements == true)
124  SetNumberOfElementsByLegendItem(begin, end, legend);
125  }
126 
127  /*!
128  \brief It groups the values defined by a range of iterators using the quantil algorithm.
129 
130  \param begin The iterator associated to the first element value.
131  \param end The iterator associated to the last element value.
132  \param nSteps The number of steps.
133  \param legend The container of legend items.
134  \param precision The precision to be used in the conversion of the values.
135  \param countElements The flag indicating if the counting of elements must be done.
136 
137  \output The groups will be stored in the container of legend items.
138  */
139  template<class iterator>
140  void GroupingByQuantil(iterator begin, iterator end, int nSteps, std::vector<te::map::GroupingItem*>& legend,
141  int precision = 0, bool countElements = true)
142  {
143  sort(begin, end);
144 
145  int size = end - begin;
146  double steps = (double)size / (double)nSteps;
147 
148  int n = 0;
149  iterator it = begin;
150  while(it < end)
151  {
153  legendItem->setLowerLimit(te::common::Convert2String(*it, precision));
154 
155  int p = (int)(steps * (double)++n + .5);
156 
157  it = begin + p;
158  if(it < end)
159  legendItem->setUpperLimit(te::common::Convert2String(*it, precision));
160  else
161  legendItem->setUpperLimit(te::common::Convert2String(*(it-1), precision));
162 
163  legend.push_back(legendItem);
164  }
165 
166  if(end-begin > 1)
167  {
168  double min = (*begin);
169  double max = (*(end-1));
170 
171  min = te::map::AdjustToPrecision(min, precision, true);
172  legend[0]->setLowerLimit(te::common::Convert2String(min, precision));
173 
174  max = te::map::AdjustToPrecision(max, precision, false);
175  legend[legend.size()-1]->setUpperLimit(te::common::Convert2String(max, precision));
176  }
177 
178  // Set the number of elements for each slice
179  if (countElements == true)
180  SetNumberOfElementsByLegendItem(begin, end, legend);
181  }
182 
183  /*!
184  \brief It groups the values defined by a range of iterators using the standard deviation algorithm.
185 
186  \param begin The iterator associated to the first element value.
187  \param end The iterator associated to the last element value.
188  \param nDevs The number of deviations.
189  \param legend The container of legend items.
190  \param rmean The mean value.
191  \param precision The precision to be used in the conversion of the values.
192  \param countElements The flag indicating if the counting of elements must be done.
193 
194  \output The groups will be stored in the container of legend items.
195  */
196  template<class iterator>
197  void GroupingByStdDeviation(iterator begin, iterator end, double nDevs, std::vector<te::map::GroupingItem*>& legend,
198  std::string& meanTitle, int precision = 0, bool countElements = true)
199  {
200  // Compute min, max and mean
201  double min = std::numeric_limits<double>::max();
202  double max = -std::numeric_limits<double>::max();
203  long double sum = 0.;
204  long double sm2 = 0.;
205 
206  iterator it = begin;
207  while(it < end)
208  {
209  min = MIN(min, *it);
210  max = MAX(max, *it);
211  sum += (*it);
212  sm2 += ((*it) * (*it));
213  ++it;
214  }
215 
216  double count = (double)(end - begin);
217  double mean = (double)(sum/count);
218  long double var = (sm2 / count) - (mean * mean);
219  double stdDev = sqrt(var);
220 
221  double slice = stdDev * nDevs;
222 
223  std::vector<te::map::GroupingItem*> aux;
224 
225  std::string strMean = te::common::Convert2String(mean, precision);
226 
227  double val = mean;
228  while(val - slice > min - slice)
229  {
231 
232  double v = val - slice;
233 
234  legendItem->setLowerLimit(te::common::Convert2String(v, precision));
235  legendItem->setUpperLimit(te::common::Convert2String(val, precision));
236  aux.push_back(legendItem);
237  val = v;
238  }
239 
240  std::vector<te::map::GroupingItem*>::reverse_iterator sit;
241  for(sit = aux.rbegin(); sit != aux.rend(); ++sit)
242  legend.push_back(*sit);
243 
244  meanTitle = "Mean - " + strMean;
245 
246  te::map::GroupingItem* legendItemMean = new te::map::GroupingItem;
247  legendItemMean->setLowerLimit(te::common::Convert2String(mean, precision));
248  legendItemMean->setUpperLimit(te::common::Convert2String(mean, precision));
249  legendItemMean->setTitle(meanTitle);
250  legend.push_back(legendItemMean);
251 
252  val = mean;
253  while(val + slice < max + slice)
254  {
256 
257  double v = val + slice;
258 
259  legendItem->setLowerLimit(te::common::Convert2String(val, precision));
260  legendItem->setUpperLimit(te::common::Convert2String(v, precision));
261  legend.push_back(legendItem);
262 
263  val = v;
264  }
265 
266  //adjust first and last values
267  //if(legend.size() >= 3)
268  //{
269  // if(legend[0]->getTitle() != meanTitle)
270  // legend[0]->setLowerLimit(te::common::Convert2String(min, precision));
271  //
272  // if(legend[legend.size()-1]->getTitle() != meanTitle)
273  // legend[legend.size()-1]->setUpperLimit(te::common::Convert2String(max, precision));
274  //}
275 
276 
277  // Set the number of elements for each slice
278  if (countElements == true)
279  SetNumberOfElementsByLegendItem(begin, end, legend);
280  }
281 
282  /*!
283  \brief It sets the number of elements belonging to the range of values associated to each legend item.
284 
285  \param begin The begin iterator of the container of elements.
286  \param end The end iterator of the container of elements.
287  \param legend The container of legend items.
288 
289  \return The number of elements will be stored in each legend item.
290  */
291  template<class iterator>
292  void SetNumberOfElementsByLegendItem(iterator begin, iterator end, std::vector<te::map::GroupingItem*>& legend)
293  {
294  iterator it;
295  double from, to;
296  int count;
297 
298  for (unsigned int i = 0; i < legend.size(); ++i)
299  {
300  te::map::GroupingItem* legendItem = legend[i];
301 
302  from = atof(legendItem->getLowerLimit().c_str());
303  to = atof(legendItem->getUpperLimit().c_str());
304  count = 0;
305 
306  for (it = begin; it != end; ++it)
307  {
308  if(*it >= from && *it < to)
309  ++count;
310  }
311 
312  legendItem->setCount(count);
313  }
314  }
315  } // end namespace map
316 } // end namespace te
317 
318 #endif //__TERRALIB_MAPTOOLS_INTERNAL_GROUPINGALGORITHMS_H
#define MIN(a, b)
Macro that returns min between two values.
void setTitle(const std::string &title)
It sets the title of the legend item.
void GroupingByEqualSteps(iterator begin, iterator end, int nSteps, std::vector< te::map::GroupingItem * > &legend, int precision=0, bool countElements=true)
It groups the values defined by a range of iterators using the equal steps algorithm.
TEMAPEXPORT void GroupingByUniqueValues(std::vector< std::string > &inputValues, int dataType, std::vector< te::map::GroupingItem * > &legend, int precision)
It groups the values using the unique value algorithm.
#define MAX(a, b)
Macro that returns max between two values.
TEMAPEXPORT double AdjustToPrecision(double val, int precision, bool reduce=false)
It adjusts a value to the precision specified.
void GroupingByStdDeviation(iterator begin, iterator end, double nDevs, std::vector< te::map::GroupingItem * > &legend, std::string &meanTitle, int precision=0, bool countElements=true)
It groups the values defined by a range of iterators using the standard deviation algorithm...
const std::string & getUpperLimit() const
It gets the upper limit value of the legend item.
const std::string & getLowerLimit() const
It gets the lower limit value of the legend item.
A GroupingItem contains information about a grouping item associated to a layer.
Definition: GroupingItem.h:48
URI C++ Library.
#define TEMAPEXPORT
You can use this macro in order to export/import classes and functions from this module.
Definition: Config.h:60
void GroupingByQuantil(iterator begin, iterator end, int nSteps, std::vector< te::map::GroupingItem * > &legend, int precision=0, bool countElements=true)
It groups the values defined by a range of iterators using the quantil algorithm. ...
void setCount(std::size_t count)
It It sets the number of objects whose values are between the lower and upper limits.
void setUpperLimit(const std::string &to)
It sets the upper limit value of the legend item.
std::string Convert2String(boost::int16_t value)
It converts a short integer value to a string.
Definition: StringUtils.h:54
void SetNumberOfElementsByLegendItem(iterator begin, iterator end, std::vector< te::map::GroupingItem * > &legend)
It sets the number of elements belonging to the range of values associated to each legend item...
void setLowerLimit(const std::string &from)
It sets the lower limit value of the legend item.