All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
AddressGeocodingOp.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 AddressGeocodingOp.cpp
22  */
23 
24 #include "../common/StringUtils.h"
25 
26 #include "../dataaccess/dataset/DataSet.h"
27 #include "../dataaccess/dataset/DataSetAdapter.h"
28 #include "../dataaccess/dataset/DataSetType.h"
29 #include "../dataaccess/dataset/DataSetTypeConverter.h"
30 #include "../dataaccess/dataset/ObjectIdSet.h"
31 #include "../dataaccess/datasource/DataSource.h"
32 #include "../dataaccess/datasource/DataSourceCapabilities.h"
33 #include "../dataaccess/utils/Utils.h"
34 
35 #include "../datatype/Property.h"
36 #include "../datatype/StringProperty.h"
37 
38 #include "../geometry/GeometryProperty.h"
39 #include "../geometry/GeometryCollection.h"
40 #include "../geometry/LineString.h"
41 #include "../geometry/Utils.h"
42 
43 #include "../memory/DataSet.h"
44 #include "../memory/DataSetItem.h"
45 
46 #include "../statistics/core/Utils.h"
47 
48 #include "AddressGeocodingOp.h"
49 
50 // BOOST
51 #include <boost/lexical_cast.hpp>
52 
54  m_outDsetName("")
55 {
56 }
57 
59  std::string inDsetName,
60  int inSRID,
61  te::da::DataSourcePtr inAddressDsrc,
62  std::string inAddressDsetName)
63 {
64  m_inDsrc = inDsrc;
65  m_inDsetName = inDsetName;
66  m_inSRID = inSRID;
67  m_inAddressDsrc = inAddressDsrc;
68  m_inAddressDsetName = inAddressDsetName;
69 }
70 
71 void te::addressgeocoding::AddressGeocodingOp::setParams( std::vector<std::string> associatedProps,
72  std::string streetNumber)
73 {
74  m_associatedProps = associatedProps;
75  m_streetNumber = streetNumber;
76 }
77 
79  std::string finalLeft,
80  std::string initialRight,
81  std::string finalRight)
82 {
83  m_initialLeft = initialLeft;
84  m_finalLeft = finalLeft;
85  m_initialRight = initialRight;
86  m_finalRight = finalRight;
87 }
88 
90 {
91  m_outDsrc = outDsrc;
92  m_outDsetName = outDsetName;
93 }
94 
96 {
97  if (!m_inDsrc.get() || !m_inAddressDsrc.get())
98  return false;
99  if (m_inDsetName.empty() || m_inAddressDsetName.empty())
100  return false;
101  if (m_associatedProps.empty())
102  return false;
103  if (!m_outDsrc.get())
104  return false;
105  if (m_outDsetName.empty())
106  return false;
107 
108  return true;
109 }
110 
112 {
113 // Input layer encoding
114  te::common::CharEncoding dSourceEncoding = m_inDsrc->getEncoding();
115 // Input layer DataSetType
116  std::auto_ptr<te::da::DataSetType> inDataSetType = m_inDsrc->getDataSetType(m_inDsetName);
117 
118 // Input file DataSet
119  std::auto_ptr<te::da::DataSet> dsAddress = m_inAddressDsrc->getDataSet(m_inAddressDsetName);
120  dsAddress->moveBeforeFirst();
121 
122 // Output
123 std::auto_ptr<te::da::DataSetType> outDsType = getOutputDataSetType();
124 std::auto_ptr<te::mem::DataSet> dataSetMemory(new te::mem::DataSet(outDsType.get()));
125 
126  while(dsAddress->moveNext())
127  {
128  std::string query = "SELECT * FROM ";
129  query += m_inDsetName + " WHERE tsvector @@ plainto_tsquery('english', ";
130 
131  for(std::size_t i = 0; i < m_associatedProps.size(); ++i)
132  {
133  std::string value = dsAddress->getAsString(m_associatedProps[i]);
134 
135  bool changed = false;
136  value = te::common::ReplaceSpecialChars(value, changed);
137 
138  if(i == 0)
139  query+= "'"+value;
140  else
141  query+= " | "+value;
142  }
143  query+= "')";
144 
145  //Add condition in Where clause, filter result by street number.
146  if( m_streetNumber != "")
147  {
148  if(m_initialLeft != "" && m_finalLeft != "" && m_initialRight != "" && m_finalRight != "")
149  {
150  query+= " AND (" + dsAddress->getAsString(m_streetNumber) + " > " + m_initialLeft + " OR " + dsAddress->getAsString(m_streetNumber) + " > " + m_initialRight + ")"
151  " AND (" + dsAddress->getAsString(m_streetNumber) + " < " + m_finalLeft + " OR " + dsAddress->getAsString(m_streetNumber) + " < " + m_finalRight + ")";
152  }
153  else if((m_initialLeft != "" && m_finalLeft != "" && m_initialRight == "" && m_finalRight == "")||
154  (m_initialLeft != "" && m_finalLeft != "" && m_initialRight != "" && m_finalRight == "")||
155  (m_initialLeft != "" && m_finalLeft != "" && m_initialRight == "" && m_finalRight != ""))
156  {
157  query+= " AND (" + dsAddress->getAsString(m_streetNumber) + " > " + m_initialLeft + " AND " + dsAddress->getAsString(m_streetNumber) + " < " + m_finalLeft + ")";
158  }
159  else if((m_initialLeft == "" && m_finalLeft == "" && m_initialRight != "" && m_finalRight != "")||
160  (m_initialLeft == "" && m_finalLeft != "" && m_initialRight != "" && m_finalRight != "")||
161  (m_initialLeft != "" && m_finalLeft == "" && m_initialRight != "" && m_finalRight != ""))
162  {
163  query+= " AND (" + dsAddress->getAsString(m_streetNumber) + " > " + m_initialRight + " AND " + dsAddress->getAsString(m_streetNumber) + " < " + m_finalRight + ")";
164  }
165  }
166  else
167  {
168  te::dt::Property* gid = inDataSetType->getProperty(0);
169  query += " ORDER BY " + gid->getName();
170  }
171 
172 // Submit the search query.
173  std::auto_ptr<te::da::DataSet> dsQuery = m_inDsrc->query(query);
174  dsQuery->moveFirst();
175 
176 
177 
178 // Building Address Geocoding.
179  te::mem::DataSetItem* itemMemory = new te::mem::DataSetItem(dataSetMemory.get());
180 
181  if(dsQuery->size() > 0)
182  {
183  std::vector<te::dt::Property*> vecProps = inDataSetType->getProperties();
184  double initVal = boost::lexical_cast<double>(dsAddress->getDouble(m_streetNumber));
185  double finalVal = boost::lexical_cast<double>(dsAddress->getDouble(m_streetNumber));
186  double aux_val;
187  int geomPos;
188 
189  for(std::size_t i = 0; i < vecProps.size(); ++i)
190  {
191  if(vecProps[i]->getType() != te::dt::GEOMETRY_TYPE && vecProps[i]->getName() != "tsvector")
192  {
193  if(dsQuery->isNull(i) == false)
194  itemMemory->setValue(vecProps[i]->getName(), dsQuery->getValue(i).release());
195 
196  if(vecProps[i]->getName() == m_initialLeft || vecProps[i]->getName() == m_initialRight)
197  {
198  int type = vecProps[i]->getType();
199 
200  switch (type)
201  {
202  case te::dt::INT16_TYPE:
203  {
204  aux_val = dsQuery->getInt16(i);
205  if(aux_val <= initVal)
206  initVal = aux_val;
207  }
208  break;
209  case te::dt::INT32_TYPE:
210  {
211  aux_val = dsQuery->getInt32(i);
212  if(aux_val <= initVal)
213  initVal = aux_val;
214  }
215  break;
216  case te::dt::INT64_TYPE:
217  {
218  aux_val = boost::lexical_cast<double>(dsQuery->getInt64(i));
219  if(aux_val <= initVal)
220  initVal = aux_val;
221  }
222  break;
223  case te::dt::DOUBLE_TYPE:
224  {
225  aux_val = boost::lexical_cast<double>(dsQuery->getDouble(i));
226  if(aux_val <= initVal)
227  initVal = aux_val;
228  }
229  break;
231  {
232  aux_val = boost::lexical_cast<double>(dsQuery->getNumeric(i));
233  if(aux_val <= initVal)
234  initVal = aux_val;
235  }
236  break;
237  default:
238  break;
239  }
240  }
241  if(vecProps[i]->getName() == m_finalLeft || vecProps[i]->getName() == m_finalRight)
242  {
243  int type = vecProps[i]->getType();
244 
245  switch (type)
246  {
247  case te::dt::INT16_TYPE:
248  {
249  aux_val = dsQuery->getInt16(i);
250  if(aux_val >= finalVal)
251  finalVal = aux_val;
252  }
253  break;
254  case te::dt::INT32_TYPE:
255  {
256  aux_val = dsQuery->getInt32(i);
257  if(aux_val >= finalVal)
258  finalVal = aux_val;
259  }
260  break;
261  case te::dt::INT64_TYPE:
262  {
263  aux_val = boost::lexical_cast<double>(dsQuery->getInt64(i));
264  if(aux_val >= finalVal)
265  finalVal = aux_val;
266  }
267  break;
268  case te::dt::DOUBLE_TYPE:
269  {
270  aux_val = boost::lexical_cast<double>(dsQuery->getDouble(i));
271  if(aux_val >= finalVal)
272  finalVal = aux_val;
273  }
274  break;
276  {
277  aux_val = boost::lexical_cast<double>(dsQuery->getNumeric(i).c_str());
278  if(aux_val >= finalVal)
279  finalVal = aux_val;
280  }
281  break;
282  default:
283  break;
284  }
285  }
286  }
287  else if (vecProps[i]->getType() == te::dt::GEOMETRY_TYPE)
288  {
289  geomPos = i;
290  }
291  }
292 
293  std::auto_ptr<te::gm::Geometry> geom = dsQuery->getGeometry(geomPos);
294 
295  te::gm::LineString* lineString = getLineString(geom.get());
296 
297  if(!lineString)
298  continue;
299 
300  int numTarget = boost::lexical_cast<int>(dsAddress->getDouble(m_streetNumber));
301 
302  te::gm::Coord2D* target = te::gm::locateAlong(lineString, initVal, finalVal, numTarget);
303  te::gm::Point* point = new te::gm::Point(target->getX(), target->getY(), m_inSRID);
304  itemMemory->setValue(geomPos, point);
305 
306  dataSetMemory->add(itemMemory);
307  }
308  else
309  {
310  //Address not found.
311  }
312 
313  }
314 
315  // save the result
316  return save(dataSetMemory,outDsType);
317 }
318 
319 bool te::addressgeocoding::AddressGeocodingOp::save(std::auto_ptr<te::mem::DataSet> result, std::auto_ptr<te::da::DataSetType> outDsType)
320 {
321  // do any adaptation necessary to persist the output dataset
322  te::da::DataSetTypeConverter* converter = new te::da::DataSetTypeConverter(outDsType.get(), m_outDsrc->getCapabilities());
323  te::da::DataSetType* dsTypeResult = converter->getResult();
324  std::auto_ptr<te::da::DataSetAdapter> dsAdapter(te::da::CreateAdapter(result.get(), converter));
325 
326  std::map<std::string, std::string> options;
327  // create the dataset
328  m_outDsrc->createDataSet(dsTypeResult, options);
329 
330  // copy from memory to output datasource
331  result->moveBeforeFirst();
332  m_outDsrc->add(dsTypeResult->getName(),result.get(), options);
333 
334  // create the primary key if it is possible
335  if (m_outDsrc->getCapabilities().getDataSetTypeCapabilities().supportsPrimaryKey())
336  {
337  std::string pk_name = dsTypeResult->getName() + "_pkey";
338  te::da::PrimaryKey* pk = new te::da::PrimaryKey(pk_name, dsTypeResult);
339  pk->add(dsTypeResult->getProperty(0));
340  m_outDsrc->addPrimaryKey(m_outDsetName,pk);
341  }
342 
343  return true;
344 }
345 
347 {
348  std::auto_ptr<te::da::DataSetType> inDsType = m_inDsrc->getDataSetType(m_inDsetName);
349  std::auto_ptr<te::da::DataSetType> outDsType(new te::da::DataSetType(m_outDsetName));
350 
351  std::vector<te::dt::Property*> vecProps = inDsType->getProperties();
352 
353  for(std::size_t i = 0; i < vecProps.size(); ++i)
354  {
355  if(vecProps[i]->getType() != te::dt::GEOMETRY_TYPE && vecProps[i]->getName() != "tsvector")
356  {
357  outDsType->add(vecProps[i]->clone());
358  }
359  else if(vecProps[i]->getType() == te::dt::GEOMETRY_TYPE)
360  {
361  te::gm::GeometryProperty* p = dynamic_cast<te::gm::GeometryProperty*>(vecProps[i]);
362 
363  te::gm::GeometryProperty* geometry = new te::gm::GeometryProperty("geom");
365  geometry->setSRID(p->getSRID());
366 
367  outDsType->add(geometry);
368  }
369  }
370 
371  return outDsType;
372 }
373 
375 {
376  te::gm::LineString* line = 0;
377  std::vector<te::gm::LineString*> vecLines;
378 
379  getLines(geom, vecLines);
380 
381  if(vecLines.size() > 0)
382  line = vecLines[0];
383 
384  for(std::size_t i = 1; i < vecLines.size(); ++i)
385  line->Union(vecLines[i]);
386 
387  return line;
388 }
389 
390 void te::addressgeocoding::AddressGeocodingOp::getLines(te::gm::Geometry* geom, std::vector<te::gm::LineString*>& lines)
391 {
392  if(geom == 0)
393  return;
394 
395  switch(geom->getGeomTypeId())
396  {
398  getLines(dynamic_cast<te::gm::GeometryCollection*>(geom), lines);
399  break;
400 
402  getLines(dynamic_cast<te::gm::LineString*>(geom), lines);
403  break;
404 
405  default:
406  return;
407  }
408 }
409 
410 void te::addressgeocoding::AddressGeocodingOp::getLines(te::gm::GeometryCollection* gc, std::vector<te::gm::LineString*>& lines)
411 {
412  assert(gc);
413 
414  for(std::size_t i = 0; i < gc->getNumGeometries(); ++i)
415  getLines(gc->getGeometryN(i), lines);
416 }
417 
418 void te::addressgeocoding::AddressGeocodingOp::getLines(te::gm::LineString* l, std::vector<te::gm::LineString*>& lines)
419 {
420  assert(l);
421  lines.push_back(l);
422 }
void setParams(std::vector< std::string > associatedProps, std::string streetNumber)
std::size_t getNumGeometries() const
It returns the number of geometries in this GeometryCollection.
Geometric property.
void add(te::dt::Property *p)
It adds a property to the list of properties of the primary key.
Definition: PrimaryKey.h:123
void setInput(te::da::DataSourcePtr inDsrc, std::string inDsetName, int inSRID, te::da::DataSourcePtr inAddressDsrc, std::string inAddressDsetName)
void setSRID(int srid)
It sets the spatial reference system identifier associated to this property.
void setGeometryType(GeomType t)
It sets the geometry subtype.
CharEncoding
Supported charsets (character encoding).
boost::shared_ptr< DataSource > DataSourcePtr
Definition: DataSource.h:1435
A class that models the description of a dataset.
Definition: DataSetType.h:72
void setValue(std::size_t i, te::dt::AbstractData *value)
It sets the value of the i-th property.
void setNumAttributes(std::string initialLeft, std::string finalLeft, std::string initialRight, std::string finalRight)
An utility struct for representing 2D coordinates.
Definition: Coord2D.h:40
Address Geocoding operation.
std::string ReplaceSpecialChars(const std::string &str, bool &changed)
It replace special characters of a string.
Definition: StringUtils.h:537
It models a property definition.
Definition: Property.h:59
An converter for DataSetType.
Implementation of a random-access dataset class for the TerraLib In-Memory Data Access driver...
Definition: DataSet.h:65
void getLines(te::gm::Geometry *geom, std::vector< te::gm::LineString * > &lines)
LineString is a curve with linear interpolation between points.
Definition: LineString.h:62
int getSRID() const
It returns the spatial reference system identifier associated to this property.
A point with x and y coordinate values.
Definition: Point.h:50
bool save(std::auto_ptr< te::mem::DataSet > result, std::auto_ptr< te::da::DataSetType > outDsetName)
void setOutput(te::da::DataSourcePtr outDsrc, std::string m_outDsetName)
TEGEOMEXPORT Coord2D * locateAlong(const LineString *line, double initial, double final, double target)
Make the line interpolation to find a target.
Definition: Utils.cpp:169
GeomType getGeomTypeId() const
It returns the geometry subclass type identifier.
Definition: Geometry.h:178
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
Definition: Geometry.h:73
Geometry * getGeometryN(std::size_t i) const
It returns the n-th geometry in this GeometryCollection.
An implementation of the DatasetItem class for the TerraLib In-Memory Data Access driver...
Definition: DataSetItem.h:56
std::auto_ptr< te::da::DataSetType > getOutputDataSetType()
It describes a primary key (pk) constraint.
Definition: PrimaryKey.h:52
virtual Geometry * Union(const Geometry *const rhs) const
It returns a geometric object that represents the point set union with another geometry.
Definition: Geometry.cpp:544
It is a collection of other geometric objects.
TEDATAACCESSEXPORT DataSetAdapter * CreateAdapter(DataSet *ds, DataSetTypeConverter *converter, bool isOwner=false)
Definition: Utils.cpp:644
te::gm::LineString * getLineString(te::gm::Geometry *geom)
const std::string & getName() const
It returns the property name.
Definition: Property.h:127