SamplePointsGeneratorStratified.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 terralib/sa/core/SamplePointsGeneratorStratified.cpp
22 
23  \brief This file contains a class to generate samples points using stratified strategy.
24 
25  \reference Adapted from TerraLib4.
26 */
27 
28 // Terralib Includes
29 #include "../../common/Exception.h"
30 #include "../../core/translator/Translator.h"
31 #include "../../common/STLUtils.h"
32 #include "../../common/progress/TaskProgress.h"
33 #include "../../dataaccess/utils/Utils.h"
34 #include "../../datatype/SimpleProperty.h"
35 #include "../../geometry/Geometry.h"
36 #include "../../geometry/GeometryProperty.h"
37 #include "../../geometry/Polygon.h"
38 #include "../../memory/DataSet.h"
39 #include "../../memory/DataSetItem.h"
40 #include "../core/Utils.h"
41 #include "../Enums.h"
43 
45  : m_nPoints(0), m_attrName(""), m_propToArea(false)
46 {
48 }
49 
51 {
52  std::map<std::string, std::vector<te::gm::Geometry*> >::iterator it = m_classMap.begin();
53 
54  while(it != m_classMap.end())
55  {
56  std::vector<te::gm::Geometry*> geomVec = it->second;
57 
58  te::common::FreeContents(geomVec);
59 
60  ++it;
61  }
62 
63  m_classMap.clear();
64 }
65 
67 {
68  m_nPoints = nPoints;
69 }
70 
71 void te::sa::SamplePointsGeneratorStratified::setInputDataSet(std::unique_ptr<te::da::DataSet> dataSet)
72 {
73  m_dataSet = std::move(dataSet);
74 }
75 
77 {
78  m_attrName = attrName;
79 }
80 
82 {
83  m_propToArea = isProp;
84 }
85 
87 {
88  std::vector<std::string> names;
89 
90  std::map<std::string, std::vector<te::gm::Geometry*> >::iterator it = m_classMap.begin();
91 
92  while(it != m_classMap.end())
93  {
94  names.push_back(it->first);
95 
96  ++it;
97  }
98 
99  return names;
100 }
101 
103 {
104  std::unique_ptr<te::da::DataSetType> dsType(new te::da::DataSetType(m_outputDataSetName));
105 
106  //create id property
108  dsType->add(idProperty);
109 
110  //create class property
112  dsType->add(classProperty);
113 
114  //create geometry property
116  dsType->add(geomProperty);
117 
118  //create primary key
119  std::string pkName = TE_SA_SPG_ATTR_PK_NAME;
120  pkName+= "_" + m_outputDataSetName;
121  te::da::PrimaryKey* pk = new te::da::PrimaryKey(pkName, dsType.get());
122  pk->add(idProperty);
123 
124  return dsType;
125 }
126 
128 {
129  std::unique_ptr<te::mem::DataSet> ds(new te::mem::DataSet(dsType));
130 
131  //create the class map
132  createClassMap();
133 
134  std::map<std::string, int> nPointsPerClass;
135 
136  //define the number of samples for each class using the area of the polygons
137  if(m_propToArea)
138  {
139  std::map<std::string, double> areaPerClass;
140 
141  std::map<std::string, std::vector<te::gm::Geometry*> >::iterator it = m_classMap.begin();
142 
143  //calculate the total area of each class
144  std::vector<double> areas;
145 
146  while(it != m_classMap.end())
147  {
148  std::vector<te::gm::Geometry*> geomVec = it->second;
149 
150  double totArea = 0.;
151 
152  for(std::size_t t = 0; t < geomVec.size(); ++t)
153  {
154  totArea += te::sa::GetArea(geomVec[t]);
155  }
156 
157  areaPerClass.insert(std::map<std::string, double>::value_type(it->first, totArea));
158 
159  areas.push_back(totArea);
160 
161  ++it;
162  }
163 
164  //calculate the proportional number of points for each class
165  std::vector<double>::iterator minPos = std::min_element(areas.begin(), areas.end());
166  double minArea = *minPos;
167 
168  it = m_classMap.begin();
169 
170  while(it != m_classMap.end())
171  {
172  int nPoints = (int)((areaPerClass[it->first] * m_nPoints) / minArea);
173 
174  nPointsPerClass.insert(std::map<std::string, int>::value_type(it->first, nPoints));
175 
176  ++it;
177  }
178  }
179  else
180  {
181  std::map<std::string, std::vector<te::gm::Geometry*> >::iterator it = m_classMap.begin();
182 
183  //associate the default number of points for each class
184  while(it != m_classMap.end())
185  {
186  nPointsPerClass.insert(std::map<std::string, int>::value_type(it->first, m_nPoints));
187 
188  ++it;
189  }
190  }
191 
192  //create task
194 
195  task.setTotalSteps(static_cast<int>(m_classMap.size()));
196  task.setMessage(TE_TR("Creating Points by Class."));
197 
198  //generate samples
199  int idCount = 0;
200 
201  std::map<std::string, std::vector<te::gm::Geometry*> >::iterator it = m_classMap.begin();
202 
203  while(it != m_classMap.end())
204  {
205  std::string className = it->first;
206 
207  std::vector<te::gm::Geometry*> geomVec = it->second;
208 
209  m_distInt = boost::random::uniform_int_distribution<>(0, static_cast<int>(geomVec.size() - 1));
210 
211  int nPoints = nPointsPerClass[className];
212 
213  for(int i = 0; i < nPoints; ++i)
214  {
215  //create dataset item
216  te::mem::DataSetItem* item = new te::mem::DataSetItem(ds.get());
217 
218  //set id
219  item->setInt32(TE_SA_SPG_ATTR_ID_NAME, idCount);
220 
221  //set class name
222  item->setString(TE_SA_SPG_ATTR_CLASS_NAME, className);
223 
224  //set geometry
226 
227  ds->add(item);
228 
229  ++idCount;
230  }
231 
232  if(!task.isActive())
233  {
234  throw te::common::Exception(TE_TR("Operation canceled by the user."));
235  }
236 
237  task.pulse();
238 
239  ++it;
240  }
241 
242  return ds;
243 }
244 
246 {
247  m_classMap.clear();
248 
249  m_dataSet->moveBeforeFirst();
250 
251  std::size_t geomIdx = te::da::GetFirstPropertyPos(m_dataSet.get(), te::dt::GEOMETRY_TYPE);
252 
253  while(m_dataSet->moveNext())
254  {
255  //class name
256  std::string className = m_dataSet->getString(m_attrName);
257 
258  //geometry
259  te::gm::Geometry* geom = m_dataSet->getGeometry(geomIdx).release();
260 
261  std::map<std::string, std::vector<te::gm::Geometry*> >::iterator it = m_classMap.find(className);
262 
263  //insert into map
264  if(it == m_classMap.end())
265  {
266  std::vector<te::gm::Geometry*> geomVec;
267  geomVec.push_back(geom);
268 
269  m_classMap.insert(std::map<std::string, std::vector<te::gm::Geometry*> >::value_type(className, geomVec));
270  }
271  else
272  {
273  it->second.push_back(geom);
274  }
275  }
276 }
277 
279 {
280  te::gm::Point* p = nullptr;
281 
282  bool within = false;
283 
284  while(within == false)
285  {
286  p = getPoint(g->getMBR());
287 
288  if(p->within(g))
289  within = true;
290  else
291  delete p;
292  }
293 
294  return p;
295 }
std::unique_ptr< te::da::DataSet > m_dataSet
Attribute with input data.
std::string m_attrName
Attribute used to get from input data the selected attribute.
Geometric property.
void setMessage(const std::string &message)
Set the task message.
void add(te::dt::Property *p)
It adds a property to the list of properties of the primary key.
Definition: PrimaryKey.h:123
void setGeometry(std::size_t i, te::gm::Geometry *value)
It sets the value of the i-th property.
bool m_propToArea
Attribute used to indicate if the number of samples has to be proportional to the area...
An atomic property like an integer or double.
boost::random::uniform_int_distribution m_distInt
te::sa::SamplePointsGeneratorType m_type
Generator Type.
#define TE_SA_SPG_ATTR_PK_NAME
A class that models the description of a dataset.
Definition: DataSetType.h:72
This file contains a class to generate samples points using stratified strategy.
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
static te::dt::Date ds(2010, 01, 01)
#define TE_SA_SPG_ATTR_GEOM_NAME
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
std::map< std::string, std::vector< te::gm::Geometry * > > m_classMap
Attribute with polygons for each class from input dataset.
bool isActive() const
Verify if the task is active.
std::string m_outputDataSetName
Attribute that defines the output dataset name.
void setTotalSteps(int value)
Set the task total stepes.
void setInt32(std::size_t i, boost::int32_t value)
It sets the value of the i-th property.
TESAEXPORT double GetArea(te::gm::Geometry *geom)
Function used to get area of a geometry.
Implementation of a random-access dataset class for the TerraLib In-Memory Data Access driver...
te::gm::Point * getPointInGeometry(te::gm::Geometry *g)
A point with x and y coordinate values.
Definition: Point.h:50
const Envelope * getMBR() const _NOEXCEPT_OP(true)
It returns the minimum bounding rectangle for the geometry in an internal representation.
virtual bool within(const Geometry *const rhs) const _NOEXCEPT_OP(false)
It returns true if the geometry object is spatially within rhs geometry.
#define TE_SA_SPG_ATTR_ID_NAME
te::gm::Polygon * p
void pulse()
Calls setCurrentStep() function using getCurrentStep() + 1.
te::gm::Point * getPoint(const te::gm::Envelope *env)
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
An implementation of the DatasetItem class for the TerraLib In-Memory Data Access driver...
int m_nPoints
Attribute used to define the number of points to be generated.
It describes a primary key (pk) constraint.
Definition: PrimaryKey.h:52
virtual std::unique_ptr< te::da::DataSetType > createDataSetType()
void setInputDataSet(std::unique_ptr< te::da::DataSet > dataSet)
#define TE_SA_SPG_ATTR_CLASS_NAME
TEDATAACCESSEXPORT std::size_t GetFirstPropertyPos(const te::da::DataSet *dataset, int datatype)
void setString(std::size_t i, const std::string &value)
It sets the value of the i-th property.
void FreeContents(boost::unordered_map< K, V * > &m)
This function can be applied to a map of pointers. It will delete each pointer in the map...
Definition: BoostUtils.h:55
virtual std::unique_ptr< te::mem::DataSet > generateSamples(te::da::DataSetType *dsType)
virtual ~SamplePointsGeneratorStratified()
Virtual destructor.
int m_srid
Attribute with spatial reference information.