src/terralib/vp/Identity.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
4  applications.
5 
6  TerraLib is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published by
8  the Free Software Foundation, either version 3 of the License,
9  or (at your option) any later version.
10 
11  TerraLib is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with TerraLib. See COPYING. If not, write to
18  TerraLib Team at <terralib-team@terralib.org>.
19  */
20 
21 /*!
22  \file Identity.cpp
23  */
24 
25 #include "../common/StringUtils.h"
26 
27 #include "../core/logger/Logger.h"
28 #include "../core/translator/Translator.h"
29 
30 #include "../dataaccess/dataset/DataSet.h"
31 #include "../dataaccess/dataset/ObjectIdSet.h"
32 
33 #include "../dataaccess/utils/Utils.h"
34 
35 #include "../geometry/Geometry.h"
36 #include "../geometry/GeometryProperty.h"
37 
38 #include "../memory/DataSet.h"
39 #include "../memory/DataSetItem.h"
40 
41 #include "ComplexData.h"
42 #include "Identity.h"
43 #include "Utils.h"
44 
45 te::vp::Identity::Identity() = default;
46 
48 {
50 
51  // Validating parameters
52  std::vector<te::vp::InputParams> inputParams = mainParams->getInputParams();
53 
54  if(inputParams.size() < 2)
56  "It is necessary more than one item for performing the operation."));
57 
58  // Get input data.
59  std::unique_ptr<te::da::DataSetType> inputDsType(
60  inputParams[0].m_inputDataSetType);
61 
62  te::gm::GeometryProperty* inputGeomProp =
63  te::da::GetFirstGeomProperty(inputDsType.get());
64 
65  std::unique_ptr<te::da::DataSet> inputDataSet(inputParams[0].m_inputDataSet);
66 
67  std::string inputDsName = inputDsType->getName();
68 
69  std::vector<std::string> tokens;
70  te::common::Tokenize(inputDsName, tokens, ".");
71 
72  if(tokens.size() > 1)
73  inputDsName = tokens[1];
74  else
75  inputDsName = tokens[0];
76 
77  // Get intersection data.
78  std::unique_ptr<te::da::DataSetType> intersectionDsType(
79  inputParams[1].m_inputDataSetType);
80 
81  te::gm::GeometryProperty* intersectionGeomProp =
82  te::da::GetFirstGeomProperty(intersectionDsType.get());
83 
84  std::unique_ptr<te::da::DataSet> intersectionDataSet(
85  inputParams[1].m_inputDataSet);
86 
87  std::string intersectionDsName = intersectionDsType->getName();
88 
89  tokens.clear();
90  te::common::Tokenize(intersectionDsName, tokens, ".");
91 
92  if(tokens.size() > 1)
93  intersectionDsName = tokens[1];
94  else
95  intersectionDsName = tokens[0];
96 
97  // Get output datasource.
98  te::da::DataSourcePtr outputDataSource = mainParams->getOutputDataSource();
99 
100  // Build output dataset type
101  std::unique_ptr<te::da::DataSetType> outputDataSetType(
102  getOutputDataSetType(mainParams));
103 
104  // Get the first geometry property from output datasettype.
105  te::gm::GeometryProperty* geomProp =
106  te::da::GetFirstGeomProperty(outputDataSetType.get());
107 
108  // Insert intersection dataset in rtree.
110 
111  // Get specific params.
112  const std::map<std::string, te::dt::AbstractData*>& specificParams =
113  mainParams->getSpecificParams();
114 
115  // Create output dataset in memory.
116  std::unique_ptr<te::mem::DataSet> outputDataSet(
117  new te::mem::DataSet(outputDataSetType.get()));
118 
119  size_t p = 0;
120  int inputSRID = inputGeomProp->getSRID();
121  int intersectionSRID = intersectionGeomProp->getSRID();
122 
123  std::string intupGeomName = inputGeomProp->getName();
124  std::string intersectionGeomName = intersectionGeomProp->getName();
125 
126  intersectionDataSet->moveBeforeFirst();
127  while(intersectionDataSet->moveNext())
128  {
129  try
130  {
131  if (intersectionDataSet->isNull(intersectionGeomName))
132  continue;
133 
134  std::unique_ptr<te::gm::Geometry> g =
135  intersectionDataSet->getGeometry(intersectionGeomName);
136 
137  if(!g->isValid())
138  continue;
139 
140  rtree->insert(*g->getMBR(), p);
141  ++p;
142  }
143  catch(te::common::Exception& e)
144  {
145  TE_LOG_ERROR("Vector Processing - Identity - Intersection Layer: " + e.what());
146  continue;
147  }
148  }
149 
150  std::vector<std::string> inputPropNames =
151  this->getPropNames(specificParams, inputDsType->getName());
152 
153  std::vector<std::string> intersectionPropNames =
154  this->getPropNames(specificParams, intersectionDsType->getName());
155 
156  inputDataSet->moveBeforeFirst();
157  while(inputDataSet->moveNext())
158  {
159  try
160  {
161  // Create DataSetItem based on output DataSet;
162  std::unique_ptr<te::mem::DataSetItem> item(
163  new te::mem::DataSetItem(outputDataSet.get()));
164 
165  // Populate item with tabular data.
166  for(std::size_t p = 0; p < inputPropNames.size(); ++p)
167  {
168  int pos = static_cast<int>(inputDsType->getPropertyPosition(inputPropNames[p]));
169 
170  if(!inputDataSet->isNull(pos))
171  {
172  item->setValue("A_" + inputPropNames[p],
173  inputDataSet->getValue(pos).release());
174  }
175  }
176 
177  if(inputDataSet->isNull(intupGeomName))
178  continue;
179 
180  // Current geometry from Input Layer.
181  std::unique_ptr<te::gm::Geometry> inputGeometry =
182  inputDataSet->getGeometry(intupGeomName);
183 
184  if(!inputGeometry->isValid())
185  continue;
186 
187  // If is different srid, transform current geom to the "intersection"
188  // projection, to search in rtree the candidates.
189  if(inputSRID != intersectionSRID)
190  inputGeometry->transform(intersectionSRID);
191 
192  std::vector<size_t> report;
193  rtree->search(*inputGeometry->getMBR(), report);
194 
195  // If the geom SRID was changed, return to original SRID.
196  if(inputGeometry->getSRID() != inputSRID)
197  inputGeometry->transform(inputSRID);
198 
199  // If the search is empty, insert this item into Output dataSet;
200  if(report.empty())
201  {
202  std::vector<te::gm::Geometry*> inputGeomVec;
203 
204  te::gm::Multi2Single(inputGeometry.get(), inputGeomVec);
205 
206  for(std::size_t g = 0; g < inputGeomVec.size(); ++g)
207  {
208  if(geomProp->getGeometryType() == inputGeomVec[g]->getGeomTypeId())
209  {
210  std::unique_ptr<te::mem::DataSetItem> currentItem = item->clone();
211  currentItem->setGeometry(geomProp->getName(), inputGeomVec[g]);
212  outputDataSet->add(currentItem.release());
213  }
214  }
215 
216  continue;
217  }
218 
219  // Difference and Intersection Operation.
220  std::vector<te::gm::Geometry*> geomUnionVec;
221 
222  for(size_t i = 0; i < report.size(); ++i)
223  {
224  intersectionDataSet->move(report[i]);
225 
226  std::unique_ptr<te::gm::Geometry> geometry =
227  intersectionDataSet->getGeometry(intersectionGeomName);
228 
229  if(geometry->getSRID() != inputSRID)
230  geometry->transform(inputSRID);
231 
232  std::unique_ptr<te::mem::DataSetItem> intersectionItem = item->clone();
233 
234  // Populate item with tabular data.
235  for(std::size_t p = 0; p < intersectionPropNames.size(); ++p)
236  {
237  int pos = static_cast<int>(intersectionDsType->getPropertyPosition(intersectionPropNames[p]));
238 
239  if(!intersectionDataSet->isNull(pos))
240  {
241  intersectionItem->setValue("B_" + intersectionPropNames[p],
242  intersectionDataSet->getValue(pos).release());
243  }
244  }
245 
246  geomUnionVec.push_back(
247  dynamic_cast<te::gm::Geometry*>(geometry->clone()));
248 
249  geometry.reset(geometry->intersection(inputGeometry.get()));
250  if(!geometry->isEmpty())
251  {
252  // Insert the current geometry into item;
253  std::vector<te::gm::Geometry*> intersectionGeomVec;
254 
255  te::gm::Multi2Single(geometry.get(), intersectionGeomVec);
256 
257  for(std::size_t g = 0; g < intersectionGeomVec.size(); ++g)
258  {
259  if(geomProp->getGeometryType() ==
260  intersectionGeomVec[g]->getGeomTypeId())
261  {
262  std::unique_ptr<te::mem::DataSetItem> currentItem =
263  intersectionItem->clone();
264 
265  currentItem->setGeometry(geomProp->getName(),
266  intersectionGeomVec[g]);
267 
268  outputDataSet->add(currentItem.release());
269  }
270  }
271  }
272  }
273 
274  std::unique_ptr<te::gm::Geometry> geometryUnion;
275  if(!geomUnionVec.empty())
276  geometryUnion = te::gm::GetGeometryUnion(geomUnionVec);
277 
278  if(geometryUnion.get())
279  {
280  if(inputSRID != intersectionSRID)
281  geometryUnion->transform(inputSRID);
282 
283  inputGeometry.reset(inputGeometry->difference(geometryUnion.get()));
284  }
285 
286  if(!inputGeometry->isEmpty())
287  {
288  // Insert the current geometry into item;
289  std::vector<te::gm::Geometry*> inputGeomVec;
290 
291  te::gm::Multi2Single(inputGeometry.get(), inputGeomVec);
292 
293  for(std::size_t g = 0; g < inputGeomVec.size(); ++g)
294  {
295  std::unique_ptr<te::mem::DataSetItem> currentItem = item->clone();
296  currentItem->setGeometry(geomProp->getName(), inputGeomVec[g]);
297  outputDataSet->add(currentItem.release());
298  }
299  }
300  }
301  catch(te::common::Exception& e)
302  {
303  TE_LOG_ERROR("Vector Processing - Identity - Input Layer: " + e.what());
304  continue;
305  }
306  }
307 
308  std::unique_ptr<te::da::DataSet> dataSetPrepared =
309  PrepareAdd(outputDataSet.release(), outputDataSetType.get());
310 
311  if(!dataSetPrepared.get())
312  throw te::common::Exception(
313  TE_TR("Output DataSet was not prepared to save."));
314 
315  if(dataSetPrepared->size() == 0)
316  throw te::common::Exception("The resultant layer is empty!");
317 
318  Save(outputDataSource.get(), dataSetPrepared.get(), outputDataSetType.get());
319 
320  return true;
321 }
322 
324 {
325  return false;
326 }
327 
328 std::vector<std::string> te::vp::Identity::getPropNames(
329  const std::map<std::string, te::dt::AbstractData*>& specificParams,
330  const std::string& dataSetName)
331 {
332  std::vector<std::string> propNameVec;
333 
334  if(specificParams.empty())
335  return propNameVec;
336 
337  std::map<std::string, te::dt::AbstractData*>::const_iterator it =
338  specificParams.find(dataSetName);
339 
340  if(it != specificParams.end())
341  {
344  it->second);
345 
346  if(cd)
347  propNameVec = cd->getValue();
348  }
349 
350  return propNameVec;
351 }
352 
354  te::vp::AlgorithmParams* mainParams)
355 {
356  // Get the input parameters
357  std::vector<te::vp::InputParams> inputParams = mainParams->getInputParams();
358 
359  // Get the output dataset name.
360  std::string outputDataSetName = mainParams->getOutputDataSetName();
361  te::da::DataSetType* outputDataSetType =
362  new te::da::DataSetType(outputDataSetName);
363 
364  // Set to output datasettype the primary key property.
365  if(mainParams->getOutputDataSource()->getType() != "OGR")
366  {
368  outputDataSetName + "_id", te::dt::INT32_TYPE);
369  pkProperty->setAutoNumber(true);
370  outputDataSetType->add(pkProperty);
371 
372  te::da::PrimaryKey* pk =
373  new te::da::PrimaryKey(outputDataSetName + "_pk", outputDataSetType);
374  pk->add(pkProperty);
375  outputDataSetType->setPrimaryKey(pk);
376  }
377 
378  // Get input geometry property.
379  te::gm::GeometryProperty* intputGeomProp=nullptr;
380 
381  // Get tabular attributes.
382  const std::map<std::string, te::dt::AbstractData*> specificParams =
383  mainParams->getSpecificParams();
384 
385  te::da::DataSetType* dsType = nullptr;
386 
387  for(std::size_t i = 0; i < inputParams.size(); ++i)
388  {
389  if(inputParams[i].m_inputDataSetType)
390  dsType = inputParams[i].m_inputDataSetType;
391  else
392  dsType =
393  te::da::GetDataSetType(inputParams[i].m_inputDataSetName,
394  inputParams[i].m_inputDataSource->getId());
395 
396  std::string alias;
397 
398  if(i == 0)
399  {
400  alias = "A_";
401  intputGeomProp = te::da::GetFirstGeomProperty(dsType);
402  }
403  else
404  {
405  alias = "B_";
406  }
407 
408  std::vector<std::string> propNames =
409  getPropNames(specificParams, dsType->getName());
410 
411  for(std::size_t i = 0; i < propNames.size(); ++i)
412  {
413  te::dt::Property* prop = dsType->getProperty(propNames[i])->clone();
414 
415  prop->setName(alias + propNames[i]);
416 
417  if(!prop)
418  continue;
419 
420  outputDataSetType->add(prop);
421  }
422  }
423 
424  // Get input geometry property.
425  te::gm::GeomType inputGeomType = intputGeomProp->getGeometryType();
426  te::gm::GeomType outputGeomType;
427 
428  if(te::gm::IsMultiType(inputGeomType))
429  outputGeomType = te::gm::GetSimpleType(inputGeomType);
430  else
431  outputGeomType = inputGeomType;
432 
433  // Creating the geometry property.
434  te::gm::GeometryProperty* newGeomProp = new te::gm::GeometryProperty("geom");
435  newGeomProp->setGeometryType(outputGeomType);
436  newGeomProp->setSRID(intputGeomProp->getSRID());
437 
438  outputDataSetType->add(newGeomProp);
439 
440  return outputDataSetType;
441 }
Identity operation.
void setAutoNumber(bool a)
It tells if the property is an autonumber or not.
Property * getProperty(std::size_t i) const
It returns the i-th property.
Geometric property.
TEVPEXPORT std::unique_ptr< te::da::DataSet > PrepareAdd(te::da::DataSet *ds, te::da::DataSetType *dt)
void add(te::dt::Property *p)
It adds a property to the list of properties of the primary key.
Definition: PrimaryKey.h:123
GeomType
Each enumerated type is compatible with a Well-known Binary (WKB) type code.
void setSRID(int srid)
It sets the spatial reference system identifier associated to this property.
void setGeometryType(GeomType t)
It sets the geometry subtype.
An atomic property like an integer or double.
boost::shared_ptr< DataSource > DataSourcePtr
A class that represents an R-tree.
A class that models the description of a dataset.
Definition: DataSetType.h:72
virtual const char * what() const
It outputs the exception message.
TEGEOMEXPORT bool IsMultiType(te::gm::GeomType geomType)
Verifies if the geomType is a collection type.
std::vector< te::vp::InputParams > getInputParams()
TEGEOMEXPORT std::unique_ptr< te::gm::Geometry > GetGeometryUnion(const std::vector< te::gm::Geometry * > &geomVec)
It returns the union of a geometry vector.
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.
bool executeQuery(te::vp::AlgorithmParams *mainParams)
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
T getValue() const
It returns the associated value.
Definition: ComplexData.h:129
TEVPEXPORT void Save(te::da::DataSource *source, te::da::DataSet *result, te::da::DataSetType *outDsType, const bool &enableProgress=true)
void Tokenize(const std::string &str, std::vector< std::string > &tokens, const std::string &delimiters=" ")
It tokenizes a given string with a delimiter of your own choice.
Definition: StringUtils.h:221
Implementation of a random-access dataset class for the TerraLib In-Memory Data Access driver...
bool executeMemory(te::vp::AlgorithmParams *mainParams)
void setName(const std::string &name)
It sets the property name.
Definition: Property.h:137
A template for complex data types.
Definition: ComplexData.h:52
int getSRID() const
It returns the spatial reference system identifier associated to this property.
const std::string & getOutputDataSetName()
GeomType getGeometryType() const
It returns the geometry subtype allowed for the property.
te::gm::Polygon * p
te::da::DataSourcePtr getOutputDataSource()
const std::map< std::string, te::dt::AbstractData * > & getSpecificParams()
Utility functions for the data access module.
te::da::DataSetType * getOutputDataSetType(te::vp::AlgorithmParams *mainParams)
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
std::vector< std::string > getPropNames(const std::map< std::string, te::dt::AbstractData * > &specificParams, const std::string &dataSetName)
void add(Constraint *c)
It adds a new constraint.
An implementation of the DatasetItem class for the TerraLib In-Memory Data Access driver...
It describes a primary key (pk) constraint.
Definition: PrimaryKey.h:52
#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
TEVPEXPORT void ValidateAlgorithmParams(AlgorithmParams *mainParams, Strategy st)
TEDATAACCESSEXPORT DataSetType * GetDataSetType(const std::string &name, const std::string &datasourceId)
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
void setPrimaryKey(PrimaryKey *pk)
It sets the primary key constraint.
const std::string & getName() const
It returns the property name.
Definition: Property.h:127