MultipartToSinglepart.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 MultipartToSinglepart.h
22 
23  \brief Multipart to Singlepart Vector Processing functions.
24 */
25 
26 //Terralib
27 
28 #include "../common/progress/TaskProgress.h"
29 #include "../core/logger/Logger.h"
30 #include "../core/translator/Translator.h"
31 
32 #include "../dataaccess/dataset/DataSet.h"
33 #include "../dataaccess/dataset/ObjectId.h"
34 #include "../dataaccess/dataset/ObjectIdSet.h"
35 #include "../dataaccess/utils/Utils.h"
36 #include "../datatype/Property.h"
37 #include "../datatype/SimpleProperty.h"
38 #include "../datatype/StringProperty.h"
39 
40 #include "../geometry/Geometry.h"
41 #include "../geometry/GeometryProperty.h"
42 #include "../geometry/MultiLineString.h"
43 #include "../geometry/MultiPoint.h"
44 #include "../geometry/MultiPolygon.h"
45 #include "../geometry/Utils.h"
46 
47 #include "../memory/DataSet.h"
48 #include "../memory/DataSetItem.h"
49 
50 #include "MultipartToSinglepart.h"
51 #include "Config.h"
52 #include "Exception.h"
53 #include "Utils.h"
54 
55 // STL
56 #include <map>
57 #include <cmath>
58 #include <string>
59 #include <vector>
60 
61 // BOOST
62 #include <boost/lexical_cast.hpp>
63 #include <boost/algorithm/string.hpp>
64 
66  : m_oidSet(nullptr)
67 {
68 }
69 
71 
73 {
75  te::gm::GeometryProperty* geomProp = dynamic_cast<te::gm::GeometryProperty*>(prop);
76 
77  if(!te::gm::IsMultiType(geomProp->getGeometryType()))
78  {
79  throw te::common::Exception(TE_TR("This layer has not a multipart geometry!"));
80  }
81 
82  if(m_oidSet)
83  return runSelected();
84  else
85  return runAll();
86 }
87 
89 {
90  std::unique_ptr<te::da::DataSet> inDs;
91 
92  inDs = m_inDsrc->getDataSet(m_inDsName);
93 
94  std::size_t geomPos = te::da::GetFirstSpatialPropertyPos(inDs.get());
95 
96  std::unique_ptr<te::da::DataSetType> outDst = getOutDst();
97 
98  std::unique_ptr<te::mem::DataSet> outDs(new te::mem::DataSet(outDst.get()));
99 
100  inDs->moveBeforeFirst();
101 
102  int pkCount = 0;
103 
104  while(inDs->moveNext())
105  {
106  try
107  {
108  if (inDs->isNull(geomPos))
109  continue;
110 
111  std::unique_ptr<te::gm::Geometry> geom = inDs->getGeometry(geomPos);
112 
113  std::vector<te::gm::Geometry*> geoms;
114  te::gm::Multi2Single(geom.release(), geoms);
115 
116  if(geoms.size() == 1)
117  {
118  te::mem::DataSetItem* item = new te::mem::DataSetItem(outDs.get());
119 
120  for(std::size_t i = 0; i < inDs->getNumProperties(); ++i)
121  {
122  if(i == 0)
123  {
124  item->setInt32(0, (int32_t)pkCount);
125  ++pkCount;
126  item->setValue(1, inDs->getValue(i).release());
127  }
128  else if(i != geomPos)
129  item->setValue((i+1), inDs->getValue(i).release());
130  else
131  item->setGeometry((i+1), geoms[0]);
132  }
133 
134  outDs->add(item);
135  }
136  else
137  {
138  for(std::size_t g = 0; g < geoms.size(); ++g)
139  {
140  te::mem::DataSetItem* item = new te::mem::DataSetItem(outDs.get());
141 
142  for(std::size_t i = 0; i < inDs->getNumProperties(); ++i)
143  {
144  if(i == 0)
145  {
146  item->setInt32(0, (int32_t)pkCount);
147  ++pkCount;
148  item->setValue(1, inDs->getValue(i).release());
149  }
150  else if(i != geomPos)
151  item->setValue((i+1), inDs->getValue(i).release());
152  else
153  item->setGeometry((i+1), geoms[g]);
154  }
155 
156  outDs->add(item);
157  }
158  }
159  }
160  catch(te::common::Exception& e)
161  {
162  TE_LOG_ERROR("Vector Processing - Multipart to Singlepart - " + e.what());
163  continue;
164  }
165  }
166 
167  te::vp::Save(m_outDsrc.get(), outDs.get(), outDst.get());
168 
169  return true;
170 }
171 
173 {
174  std::unique_ptr<te::da::DataSet> inDs;
175 
176  inDs = m_inDsrc->getDataSet(m_inDsName);
177 
178  std::size_t geomPos = te::da::GetFirstSpatialPropertyPos(inDs.get());
179 
180  std::unique_ptr<te::da::DataSetType> outDst = getOutDst(true);
181 
182  std::unique_ptr<te::mem::DataSet> outDs(new te::mem::DataSet(outDst.get()));
183 
184  inDs->moveBeforeFirst();
185 
186  int pkCount = 0;
187 
188  while(inDs->moveNext())
189  {
190  try
191  {
192  if (inDs->isNull(geomPos))
193  continue;
194 
195  std::unique_ptr<te::gm::Geometry> geom = inDs->getGeometry(geomPos);
196 
198 
199  std::vector<te::gm::Geometry*> geoms;
200  std::vector<te::gm::Geometry*> multiGeoms;
201 
202  if(m_oidSet->contains(geomOid))
203  {
204  te::gm::Multi2Single(geom.release(), geoms);
205 
206  for(std::size_t i = 0; i < geoms.size(); ++i)
207  {
208  multiGeoms.push_back(single2multi(geoms[i]));
209  }
210  }
211  else
212  {
213  geoms.push_back(geom.release());
214  }
215 
216  if(geoms.size() == 1)
217  {
218  te::mem::DataSetItem* item = new te::mem::DataSetItem(outDs.get());
219 
220  for(std::size_t i = 0; i < inDs->getNumProperties(); ++i)
221  {
222  if(i == 0)
223  {
224  item->setInt32(0, (int32_t)pkCount);
225  ++pkCount;
226  item->setValue(1, inDs->getValue(i).release());
227  }
228  else if(i != geomPos)
229  item->setValue((i+1), inDs->getValue(i).release());
230  else
231  item->setGeometry((i+1), geoms[0]);
232  }
233 
234  outDs->add(item);
235  }
236  else
237  {
238  for(std::size_t g = 0; g < multiGeoms.size(); ++g)
239  {
240  te::mem::DataSetItem* item = new te::mem::DataSetItem(outDs.get());
241 
242  for(std::size_t i = 0; i < inDs->getNumProperties(); ++i)
243  {
244  if(i == 0)
245  {
246  item->setInt32(0, (int32_t)pkCount);
247  ++pkCount;
248  item->setValue(1, inDs->getValue(i).release());
249  }
250  else if(i != geomPos)
251  item->setValue((i+1), inDs->getValue(i).release());
252  else
253  item->setGeometry((i+1), multiGeoms[g]);
254  }
255 
256  outDs->add(item);
257  }
258  }
259  }
260  catch(te::common::Exception& e)
261  {
262  TE_LOG_ERROR("Vector Processing - Multipart to Singlepart - " + e.what());
263  continue;
264  }
265  }
266 
267  te::vp::Save(m_outDsrc.get(), outDs.get(), outDst.get());
268  return true;
269 }
270 
272  std::string inDsName,
273  std::unique_ptr<te::da::DataSetType> inDsType,
274  const te::da::ObjectIdSet* oidSet)
275 {
276  m_inDsrc = inDsrc;
277  m_inDsName = inDsName;
278  m_inDsType = std::move(inDsType);
279  m_oidSet = oidSet;
280 }
281 
283 {
284  m_outDsrc = outDsrc;
285  m_outDsName = outDsName;
286 }
287 
288 std::unique_ptr<te::da::DataSetType> te::vp::MultipartToSinglepart::getOutDst(bool onlySelected)
289 {
290  std::unique_ptr<te::da::DataSetType> outDst(new te::da::DataSetType(m_outDsName));
291 
292  te::dt::Property* newId = new te::dt::SimpleProperty("newid", te::dt::INT32_TYPE, true);
293 
294  outDst->add(newId);
295 
296  te::da::PrimaryKey* pk = new te::da::PrimaryKey(m_outDsName + "mpk", outDst.get());
297  std::vector<te::dt::Property*> pkProps{ newId };
298 
299  pk->setProperties(pkProps);
300 
301  outDst->setPrimaryKey(pk);
302 
303  for(std::size_t i = 0; i < m_inDsType->size(); ++i)
304  {
305  te::dt::Property* oldP = m_inDsType->getProperty(i);
306  te::dt::Property* newP = oldP->clone();
307 
308  if(!onlySelected)
309  {
310  if(newP->getType() == te::dt::GEOMETRY_TYPE)
311  {
312  te::gm::GeometryProperty* geomP = dynamic_cast<te::gm::GeometryProperty*>(newP);
313 
315  }
316  }
317 
318  outDst->add(newP);
319  }
320 
321  return outDst;
322 }
323 
325 {
326  switch(geom->getGeomTypeId())
327  {
329  {
331  g->add(geom);
332  g->setSRID(geom->getSRID());
333  return g;
334  }
336  {
338  g->add(geom);
339  g->setSRID(geom->getSRID());
340  return g;
341  }
343  {
345  g->add(geom);
346  g->setSRID(geom->getSRID());
347  return g;
348  }
350  {
352  g->add(geom);
353  g->setSRID(geom->getSRID());
354  return g;
355  }
356  case te::gm::PointType:
357  {
359  g->add(geom);
360  g->setSRID(geom->getSRID());
361  return g;
362  }
363  case te::gm::PointMType:
364  {
366  g->add(geom);
367  g->setSRID(geom->getSRID());
368  return g;
369  }
370  case te::gm::PointZType:
371  {
373  g->add(geom);
374  g->setSRID(geom->getSRID());
375  return g;
376  }
377  case te::gm::PointZMType:
378  {
380  g->add(geom);
381  g->setSRID(geom->getSRID());
382  return g;
383  }
384  case te::gm::PolygonType:
385  {
387  g->add(geom);
388  g->setSRID(geom->getSRID());
389  return g;
390  }
392  {
394  g->add(geom);
395  g->setSRID(geom->getSRID());
396  return g;
397  }
399  {
401  g->add(geom);
402  g->setSRID(geom->getSRID());
403  return g;
404  }
406  {
408  g->add(geom);
409  g->setSRID(geom->getSRID());
410  return g;
411  }
412  default:
413  return nullptr;
414  }
415 }
An exception class for the Vector processing module.
MultiPolygon is a MultiSurface whose elements are Polygons.
Definition: MultiPolygon.h:50
Geometric property.
void setGeometry(std::size_t i, te::gm::Geometry *value)
It sets the value of the i-th property.
te::gm::Geometry * single2multi(te::gm::Geometry *geom)
void setGeometryType(GeomType t)
It sets the geometry subtype.
An atomic property like an integer or double.
TEDATAACCESSEXPORT ObjectId * GenerateOID(DataSet *dataset, const std::vector< std::string > &names)
boost::shared_ptr< DataSource > DataSourcePtr
A class that models the description of a dataset.
Definition: DataSetType.h:72
virtual const char * what() const
It outputs the exception message.
GeomType getGeomTypeId() const _NOEXCEPT_OP(true)
It returns the geometry subclass type identifier.
std::unique_ptr< te::da::DataSetType > m_inDsType
void setValue(std::size_t i, te::dt::AbstractData *value)
It sets the value of the i-th property.
TEGEOMEXPORT bool IsMultiType(te::gm::GeomType geomType)
Verifies if the geomType is a collection type.
TEGEOMEXPORT te::gm::GeomType GetSimpleType(te::gm::GeomType geomType)
Get the simple type of GeomType.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
virtual Property * clone() const =0
It returns a clone of the object.
TEGEOMEXPORT void Multi2Single(const te::gm::Geometry *g, std::vector< te::gm::Geometry * > &geoms)
It will get a GeometryCollection and distribute in a vector.
It models a property definition.
Definition: Property.h:59
void setInt32(std::size_t i, boost::int32_t value)
It sets the value of the i-th property.
TEVPEXPORT void Save(te::da::DataSource *source, te::da::DataSet *result, te::da::DataSetType *outDsType, const bool &enableProgress=true)
Implementation of a random-access dataset class for the TerraLib In-Memory Data Access driver...
int getSRID() const _NOEXCEPT_OP(true)
It returns the Spatial Reference System ID associated to this geometric object.
MultiPoint is a GeometryCollection whose elements are restricted to points.
Definition: MultiPoint.h:50
TEDATAACCESSEXPORT std::size_t GetFirstSpatialPropertyPos(const te::da::DataSet *dataset)
It returns the first dataset spatial property or NULL if none is found.
void setOutput(te::da::DataSourcePtr outDsrc, std::string outDsName)
This class represents a set of unique ids created in the same context. i.e. from the same data set...
Definition: ObjectIdSet.h:55
This class represents an unique id for a data set element.
void setInput(te::da::DataSourcePtr inDsrc, std::string inDsName, std::unique_ptr< te::da::DataSetType > inDsType, const te::da::ObjectIdSet *oidSet=0)
GeomType getGeometryType() const
It returns the geometry subtype allowed for the property.
void setProperties(const std::vector< te::dt::Property * > &properties)
It sets the properties that form the primary key.
Definition: PrimaryKey.h:116
Utility functions for the data access module.
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.
int getType() const
It returns the property data type.
Definition: Property.h:161
MultiLineString is a MultiCurve whose elements are LineStrings.
An implementation of the DatasetItem class for the TerraLib In-Memory Data Access driver...
void setSRID(int srid)
It sets the Spatial Reference System ID of the geometry collection and all its parts.
It describes a primary key (pk) constraint.
Definition: PrimaryKey.h:52
void add(Geometry *g)
It adds the geometry into the collection.
std::unique_ptr< te::da::DataSetType > getOutDst(bool onlySelected=false)
Configuration flags for the Terrralib Vector Processing module.
bool contains(ObjectId *oid) const
It returns if the object id set contains the given oid.
#define TE_LOG_ERROR(message)
Use this tag in order to log a message to the TerraLib default logger with the ERROR level...
Definition: Logger.h:337
const std::vector< std::string > & getPropertyNames() const
It returns the property names used to generated the oids.
Multipart to Singlepart Vector Processing functions.
TEDATAACCESSEXPORT te::dt::Property * GetFirstSpatialProperty(const DataSetType *dt)
const te::da::ObjectIdSet * m_oidSet