IntersectionMemory.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 IntersectionMemory.h
22 
23  \brief Intersection 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/DataSetAdapter.h"
34 #include "../dataaccess/utils/Utils.h"
35 #include "../datatype/Property.h"
36 
37 #include "../datatype/SimpleProperty.h"
38 #include "../datatype/StringProperty.h"
39 
40 #include "../geometry/Geometry.h"
41 #include "../geometry/GeometryCollection.h"
42 #include "../geometry/GeometryProperty.h"
43 #include "../geometry/MultiLineString.h"
44 #include "../geometry/MultiPoint.h"
45 #include "../geometry/MultiPolygon.h"
46 #include "../geometry/Utils.h"
47 
48 #include "../memory/DataSet.h"
49 #include "../memory/DataSetItem.h"
50 
51 #include "../sam.h"
52 
53 #include "IntersectionMemory.h"
54 #include "Config.h"
55 #include "Exception.h"
56 #include "Utils.h"
57 
58 // STL
59 #include <map>
60 #include <cmath>
61 #include <string>
62 #include <vector>
63 
64 // BOOST
65 #include <boost/lexical_cast.hpp>
66 #include <boost/algorithm/string.hpp>
67 
69 
71 
73 {
74  std::vector<te::dt::Property*> firstProps = getTabularProps(m_firstConverter->getResult());
75 
76  IntersectionMember firstMember;
77  firstMember.dt = m_firstConverter->getResult();
78 
79  if (m_firstOidSet == nullptr)
80  {
81  firstMember.ds = te::da::CreateAdapter(m_firstDs.release(), m_firstConverter.get());
82  }
83  else
84  {
85  if (m_isFistQuery)
86  firstMember.ds = te::da::CreateAdapter(m_firstDs.release(), m_firstConverter.get());
87  else
88  firstMember.ds = te::da::CreateAdapter(m_inFirstDsrc->getDataSet(m_inFirstDsetName, m_firstOidSet).release(), m_firstConverter.get());
89  }
90 
91  firstMember.props = firstProps;
92 
93  IntersectionMember secondMember;
94  secondMember.dt = m_secondConverter->getResult();
95 
96  if (m_secondOidSet == nullptr)
97  {
98  secondMember.ds = te::da::CreateAdapter(m_secondDs.release(), m_secondConverter.get());
99  }
100  else
101  {
102  if (m_isSecondQuery)
103  secondMember.ds = te::da::CreateAdapter(m_secondDs.release(), m_firstConverter.get());
104  else
105  secondMember.ds = te::da::CreateAdapter(m_inSecondDsrc->getDataSet(m_inSecondDsetName, m_secondOidSet).release(), m_secondConverter.get());
106  }
107 
108  secondMember.props = getTabularProps(secondMember.dt);
109 
110  std::pair<te::da::DataSetType*, te::da::DataSet*> resultPair;
111  resultPair = this->pairwiseIntersection(m_outDsetName, firstMember, secondMember);
112 
113  if(resultPair.second->size() < 1)
114  throw te::common::Exception(TE_TR("The Layers do not intersect!"));
115 
116  std::unique_ptr<te::da::DataSet> outDataSet(resultPair.second);
117  std::unique_ptr<te::da::DataSetType> outDataSetType(resultPair.first);
118 
119  te::vp::Save(m_outDsrc.get(), outDataSet.get(), outDataSetType.get());
120  return true;
121 
122 }
123 
124 std::pair<te::da::DataSetType*, te::da::DataSet*> te::vp::IntersectionMemory::pairwiseIntersection(std::string newName,
125  IntersectionMember firstMember,
126  IntersectionMember secondMember)
127 {
128 
129  //Creating the RTree with the second layer geometries
131  size_t secGeomPropPos = secondMember.dt->getPropertyPosition(secondMember.dt->findFirstPropertyOfType(te::dt::GEOMETRY_TYPE));
132  te::gm::GeometryProperty* geomProp = te::da::GetFirstGeomProperty(secondMember.dt);
133 
134  size_t secondDsCount = 0;
135  int sridSecond = -1;
136 
137  secondMember.ds->moveBeforeFirst();
138  while(secondMember.ds->moveNext())
139  {
140  if (secondMember.ds->isNull(secGeomPropPos))
141  continue;
142 
143  std::unique_ptr<te::gm::Geometry> g = secondMember.ds->getGeometry(secGeomPropPos);
144 
145  if(sridSecond == -1)
146  sridSecond = geomProp->getSRID();
147 
148  rtree->insert(*g->getMBR(), secondDsCount);
149 
150  ++secondDsCount;
151  }
152 
153  firstMember.ds->moveBeforeFirst();
154 
155  te::gm::GeometryProperty* fiGeomProp = te::da::GetFirstGeomProperty(firstMember.dt);
156  size_t fiGeomPropPos = firstMember.dt->getPropertyPosition(fiGeomProp);
157 
158  // Create the DataSetType and DataSet
159  te::da::DataSetType* outputDt = this->getOutputDsType();
160  te::mem::DataSet* outputDs = new te::mem::DataSet(outputDt);
161 
162  std::pair<te::da::DataSetType*, te::da::DataSet*> resultPair;
163 
164  te::common::TaskProgress task("Processing intersection...");
165  task.setTotalSteps((int)firstMember.ds->size());
166  task.useTimer(true);
167 
168  int pk = 0;
169 
170  while(firstMember.ds->moveNext())
171  {
172  if (firstMember.ds->isNull(fiGeomPropPos))
173  continue;
174 
175  std::unique_ptr<te::gm::Geometry> currGeom = firstMember.ds->getGeometry(fiGeomPropPos);
176 
177  if(!currGeom->isValid())
178  {
179  std::string processing = "Vector Processing";
180  std::string operation = "Intersection";
181  std::string message = "Invalid geometry in input layer.";
182 
183  TE_LOG_INFO(TE_TR(processing) + "- " + TE_TR(operation) + ": " +
184  TE_TR(message));
185 
186  continue;
187  }
188 
189  if(currGeom->getSRID() != sridSecond)
190  currGeom->transform(sridSecond);
191 
192  std::vector<size_t> report;
193  rtree->search(*currGeom->getMBR(), report);
194 
195  if(!report.empty())
196  currGeom->transform(fiGeomProp->getSRID());
197 
198  for(size_t i = 0; i < report.size(); ++i)
199  {
200  secondMember.ds->move(report[i]);
201  std::unique_ptr<te::gm::Geometry> secGeom = secondMember.ds->getGeometry(secGeomPropPos);
202  secGeom->setSRID(sridSecond);
203 
204  if(!secGeom->isValid())
205  {
206  std::string processing = "Vector Processing";
207  std::string operation = "Intersection";
208  std::string message = "Invalid geometry in overlay layer.";
209 
210  TE_LOG_INFO(TE_TR(processing) + "- " + TE_TR(operation) + ": " +
211  TE_TR(message));
212 
213  continue;
214  }
215 
216  if (secGeom->getSRID() != fiGeomProp->getSRID())
217  secGeom->transform(fiGeomProp->getSRID());
218 
219  if(!currGeom->intersects(secGeom.get()))
220  continue;
221 
222  te::mem::DataSetItem* item = new te::mem::DataSetItem(outputDs);
223  std::unique_ptr<te::gm::Geometry> resultGeom;
224 
225  if (currGeom->isValid() && secGeom->isValid())
226  resultGeom.reset(currGeom->intersection(secGeom.get()));
227 
228  if(resultGeom.get()!=nullptr && resultGeom->isValid())
229  {
231 
232  if(fiGeomProp->getGeometryType() == te::gm::MultiPolygonType)
233  {
234  if((resultGeom->getGeomTypeId() == te::gm::MultiPolygonType)
235  || (resultGeom->getGeomTypeId() == te::gm::MultiPolygonMType)
236  || (resultGeom->getGeomTypeId() == te::gm::MultiPolygonZMType)
237  || (resultGeom->getGeomTypeId() == te::gm::MultiPolygonZType))
238  {
239  item->setGeometry("geom", resultGeom.release());
240  }
241  else if((resultGeom->getGeomTypeId() == te::gm::PolygonType)
242  || (resultGeom->getGeomTypeId() == te::gm::PolygonMType)
243  || (resultGeom->getGeomTypeId() == te::gm::PolygonZMType)
244  || (resultGeom->getGeomTypeId() == te::gm::PolygonZType))
245  {
246  te::gm::MultiPolygon* newGeom = new te::gm::MultiPolygon(0, te::gm::GeomType(resultGeom->getGeomTypeId()+3), resultGeom->getSRID());
247  newGeom->add(resultGeom.release());
248  item->setGeometry("geom", newGeom);
249  }
250  }
251  else if(fiGeomProp->getGeometryType() == te::gm::MultiLineStringType)
252  {
253  if ((resultGeom->getGeomTypeId() == te::gm::MultiLineStringType)
254  || (resultGeom->getGeomTypeId() == te::gm::MultiLineStringZType)
255  || (resultGeom->getGeomTypeId() == te::gm::MultiLineStringMType)
256  || (resultGeom->getGeomTypeId() == te::gm::MultiLineStringZMType))
257  {
258  item->setGeometry("geom", resultGeom.release());
259  }
260  else if ((resultGeom->getGeomTypeId() == te::gm::LineStringType)
261  || (resultGeom->getGeomTypeId() == te::gm::LineStringZType)
262  || (resultGeom->getGeomTypeId() == te::gm::LineStringMType)
263  || (resultGeom->getGeomTypeId() == te::gm::LineStringZMType))
264  {
265  te::gm::MultiLineString* newGeom = new te::gm::MultiLineString(0, te::gm::GeomType(resultGeom->getGeomTypeId()+3), resultGeom->getSRID());
266  newGeom->add(resultGeom.release());
267  item->setGeometry("geom", newGeom);
268  }
269  }
270  else if(fiGeomProp->getGeometryType() == te::gm::MultiPointType)
271  {
272  if((resultGeom->getGeomTypeId() == te::gm::MultiPointType)
273  || (resultGeom->getGeomTypeId() == te::gm::MultiPointMType)
274  || (resultGeom->getGeomTypeId() == te::gm::MultiPointZMType)
275  || (resultGeom->getGeomTypeId() == te::gm::MultiPointZType))
276  {
277  item->setGeometry("geom", resultGeom.release());
278  }
279  else if((resultGeom->getGeomTypeId() == te::gm::PointType)
280  || (resultGeom->getGeomTypeId() == te::gm::PointKdType)
281  || (resultGeom->getGeomTypeId() == te::gm::PointMType)
282  || (resultGeom->getGeomTypeId() == te::gm::PointZMType)
283  || (resultGeom->getGeomTypeId() == te::gm::PointZType))
284  {
285  te::gm::MultiPoint* newGeom = new te::gm::MultiPoint(0, te::gm::GeomType(resultGeom->getGeomTypeId()+3), resultGeom->getSRID());
286  newGeom->add(resultGeom.release());
287  item->setGeometry("geom", newGeom);
288  }
289  }
290  }
291  else
292  {
293 #ifdef TERRALIB_LOGGER_ENABLED
294  TE_CORE_LOG_DEBUG("vp", "Intersection - Invalid geometry found");
295 #endif //TERRALIB_LOGGER_ENABLED
296  continue;
297  }
298 
299  for(size_t j = 0; j < firstMember.props.size(); ++j)
300  {
301  std::string name = firstMember.props[j]->getName();
302 
303  std::size_t inputPropPos = firstMember.dt->getPropertyPosition(name);
304 
305  std::size_t outputPropPos = outputDt->getPropertyPosition("A_" + name);
306 
307  if (outputPropPos >= outputDt->size())
308  continue;
309 
310  if (!firstMember.ds->isNull(inputPropPos))
311  {
312  te::dt::AbstractData* ad = firstMember.ds->getValue(firstMember.props[j]->getName()).release();
313  item->setValue(outputPropPos, ad);
314  }
315  }
316 
317  for(size_t j = 0; j < secondMember.props.size(); ++j)
318  {
319  std::string name = secondMember.props[j]->getName();
320 
321  std::size_t inputPropPos = secondMember.dt->getPropertyPosition(name);
322 
323  std::size_t outputPropPos = outputDt->getPropertyPosition("B_" + name);
324 
325  if (outputPropPos >= outputDt->size())
326  continue;
327 
328  if (!secondMember.ds->isNull(inputPropPos))
329  {
330  te::dt::AbstractData* ad = secondMember.ds->getValue(secondMember.props[j]->getName()).release();
331  item->setValue(outputPropPos, ad);
332  }
333  }
334 
335  item->setInt32(newName + "_id", pk);
336  ++pk;
337 
338  outputDs->moveNext();
339 
340  std::size_t aux = te::da::GetFirstSpatialPropertyPos(outputDs);
341 
342  if(!item->isNull(aux))
343  outputDs->add(item);
344  }
345 
346  if(task.isActive() == false)
347  {
348  delete outputDt;
349  delete outputDs;
350 
351  throw te::common::Exception(TE_TR("Operation canceled!"));
352  }
353 
354  task.pulse();
355  }
356 
357  outputDs->moveBeforeFirst();
358 
359  resultPair.first = outputDt;
360  resultPair.second = outputDs;
361  return resultPair;
362 }
An exception class for the Vector processing module.
std::unique_ptr< te::da::DataSet > m_firstDs
virtual std::unique_ptr< te::gm::Geometry > getGeometry(std::size_t i) const =0
Method for retrieving a geometric attribute value.
std::unique_ptr< te::da::DataSet > m_secondDs
std::vector< te::dt::Property * > getTabularProps(te::da::DataSetType *dsType)
std::string m_inSecondDsetName
MultiPolygon is a MultiSurface whose elements are Polygons.
Definition: MultiPolygon.h:50
Geometric property.
te::da::DataSetType * getOutputDsType()
GeomType
Each enumerated type is compatible with a Well-known Binary (WKB) type code.
void setGeometry(std::size_t i, te::gm::Geometry *value)
It sets the value of the i-th property.
A class that represents an R-tree.
const te::da::ObjectIdSet * m_firstOidSet
Base exception class for plugin module.
A class that models the description of a dataset.
Definition: DataSetType.h:72
bool isNull(std::size_t i) const
void useTimer(bool flag)
Used to define if task use progress timer information.
#define TE_CORE_LOG_DEBUG(channel, message)
Use this tag in order to log a message to a specified logger with the DEBUG level.
Definition: Logger.h:225
std::vector< te::dt::Property * > props
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
void setValue(std::size_t i, te::dt::AbstractData *value)
It sets the value of the i-th property.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:242
#define TE_LOG_INFO(message)
Use this tag in order to log a message to the TerraLib default logger with the INFO level...
Definition: Logger.h:315
bool isActive() const
Verify if the task is active.
te::da::DataSourcePtr m_inSecondDsrc
void add(DataSetItem *item)
It adds a new item to the dataset and takes its ownership.
virtual bool move(std::size_t i)=0
It moves the dataset internal pointer to a given position.
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.
virtual std::size_t size() const =0
It returns the collection size, if it is known.
virtual bool moveNext()=0
It moves the internal pointer to the next item of the collection.
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...
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.
int getSRID() const
It returns the spatial reference system identifier associated to this property.
Intersection Vector Processing functions.
URI C++ Library.
Definition: Attributes.h:37
void DataSet()
GeomType getGeometryType() const
It returns the geometry subtype allowed for the property.
std::pair< te::da::DataSetType *, te::da::DataSet * > pairwiseIntersection(std::string newName, IntersectionMember firstMember, IntersectionMember secondMember)
void pulse()
Calls setCurrentStep() function using getCurrentStep() + 1.
A base class for values that can be retrieved from the data access module.
Definition: AbstractData.h:57
std::unique_ptr< te::da::DataSetTypeConverter > m_firstConverter
int search(const te::gm::Envelope &mbr, std::vector< DATATYPE > &report) const
Range search query.
std::size_t size() const
It returns the number of properties of the CompositeProperty.
Utility functions for the data access module.
te::da::DataSourcePtr m_outDsrc
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
std::string m_inFirstDsetName
te::da::DataSourcePtr m_inFirstDsrc
std::unique_ptr< te::da::DataSetTypeConverter > m_secondConverter
bool moveBeforeFirst()
It moves the internal pointer to a position before the first item in the collection.
bool moveNext()
It moves the internal pointer to the next item of the collection.
MultiLineString is a MultiCurve whose elements are LineStrings.
An implementation of the DatasetItem class for the TerraLib In-Memory Data Access driver...
Property * findFirstPropertyOfType(const int t) const
returns the first property of the given data type. Caller doesn&#39;t take ownership of the returned poin...
void insert(const te::gm::Envelope &mbr, const DATATYPE &data)
It inserts an item into the tree.
virtual std::unique_ptr< te::dt::AbstractData > getValue(std::size_t i) const
Method for retrieving any other type of data value stored in the data source.
void add(Geometry *g)
It adds the geometry into the collection.
virtual bool moveBeforeFirst()=0
It moves the internal pointer to a position before the first item in the collection.
Configuration flags for the Terrralib Vector Processing module.
std::size_t getPropertyPosition(const std::string &name) const
It returns the property position based on its name.
virtual bool isNull(std::size_t i) const =0
It checks if the attribute value is NULL.
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
TEDATAACCESSEXPORT DataSetAdapter * CreateAdapter(DataSet *ds, DataSetTypeConverter *converter, bool isOwner=false)
const te::da::ObjectIdSet * m_secondOidSet