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 DataSetType
114  std::auto_ptr<te::da::DataSetType> inDataSetType = m_inDsrc->getDataSetType(m_inDsetName);
115 
116 // Input file DataSet
117  std::auto_ptr<te::da::DataSet> dsAddress = m_inAddressDsrc->getDataSet(m_inAddressDsetName);
118  dsAddress->moveBeforeFirst();
119 
120 // Output
121 std::auto_ptr<te::da::DataSetType> outDsType = getOutputDataSetType();
122 std::auto_ptr<te::mem::DataSet> dataSetMemory(new te::mem::DataSet(outDsType.get()));
123 
124  while(dsAddress->moveNext())
125  {
126  std::string query = "SELECT * FROM ";
127  query += m_inDsetName + " WHERE tsvector @@ plainto_tsquery('english', ";
128 
129  for(std::size_t i = 0; i < m_associatedProps.size(); ++i)
130  {
131  std::string value = dsAddress->getAsString(m_associatedProps[i]);
132 
133  bool changed = false;
134  value = te::common::ReplaceSpecialChars(value, changed);
135 
136  if(i == 0)
137  query+= "'"+value;
138  else
139  query+= " | "+value;
140  }
141  query+= "')";
142 
143  //Add condition in Where clause, filter result by street number.
144  if( m_streetNumber != "")
145  {
146  if(m_initialLeft != "" && m_finalLeft != "" && m_initialRight != "" && m_finalRight != "")
147  {
148  query+= " AND (" + dsAddress->getAsString(m_streetNumber) + " > " + m_initialLeft + " OR " + dsAddress->getAsString(m_streetNumber) + " > " + m_initialRight + ")"
149  " AND (" + dsAddress->getAsString(m_streetNumber) + " < " + m_finalLeft + " OR " + dsAddress->getAsString(m_streetNumber) + " < " + m_finalRight + ")";
150  }
151  else if((m_initialLeft != "" && m_finalLeft != "" && m_initialRight == "" && m_finalRight == "")||
152  (m_initialLeft != "" && m_finalLeft != "" && m_initialRight != "" && m_finalRight == "")||
153  (m_initialLeft != "" && m_finalLeft != "" && m_initialRight == "" && m_finalRight != ""))
154  {
155  query+= " AND (" + dsAddress->getAsString(m_streetNumber) + " > " + m_initialLeft + " AND " + dsAddress->getAsString(m_streetNumber) + " < " + m_finalLeft + ")";
156  }
157  else if((m_initialLeft == "" && m_finalLeft == "" && m_initialRight != "" && m_finalRight != "")||
158  (m_initialLeft == "" && m_finalLeft != "" && m_initialRight != "" && m_finalRight != "")||
159  (m_initialLeft != "" && m_finalLeft == "" && m_initialRight != "" && m_finalRight != ""))
160  {
161  query+= " AND (" + dsAddress->getAsString(m_streetNumber) + " > " + m_initialRight + " AND " + dsAddress->getAsString(m_streetNumber) + " < " + m_finalRight + ")";
162  }
163  }
164  else
165  {
166  te::dt::Property* gid = inDataSetType->getProperty(0);
167  query += " ORDER BY " + gid->getName();
168  }
169 
170 // Submit the search query.
171  std::auto_ptr<te::da::DataSet> dsQuery = m_inDsrc->query(query);
172  dsQuery->moveFirst();
173 
174 
175 
176 // Building Address Geocoding.
177  te::mem::DataSetItem* itemMemory = new te::mem::DataSetItem(dataSetMemory.get());
178 
179  if(dsQuery->size() > 0)
180  {
181  std::vector<te::dt::Property*> vecProps = inDataSetType->getProperties();
182  double initVal = boost::lexical_cast<double>(dsAddress->getDouble(m_streetNumber));
183  double finalVal = boost::lexical_cast<double>(dsAddress->getDouble(m_streetNumber));
184  double aux_val;
185  int geomPos;
186 
187  for(std::size_t i = 0; i < vecProps.size(); ++i)
188  {
189  if(vecProps[i]->getType() != te::dt::GEOMETRY_TYPE && vecProps[i]->getName() != "tsvector")
190  {
191  if(dsQuery->isNull(i) == false)
192  itemMemory->setValue(vecProps[i]->getName(), dsQuery->getValue(i).release());
193 
194  if(vecProps[i]->getName() == m_initialLeft || vecProps[i]->getName() == m_initialRight)
195  {
196  int type = vecProps[i]->getType();
197 
198  switch (type)
199  {
200  case te::dt::INT16_TYPE:
201  {
202  aux_val = dsQuery->getInt16(i);
203  if(aux_val <= initVal)
204  initVal = aux_val;
205  }
206  break;
207  case te::dt::INT32_TYPE:
208  {
209  aux_val = dsQuery->getInt32(i);
210  if(aux_val <= initVal)
211  initVal = aux_val;
212  }
213  break;
214  case te::dt::INT64_TYPE:
215  {
216  aux_val = boost::lexical_cast<double>(dsQuery->getInt64(i));
217  if(aux_val <= initVal)
218  initVal = aux_val;
219  }
220  break;
221  case te::dt::DOUBLE_TYPE:
222  {
223  aux_val = boost::lexical_cast<double>(dsQuery->getDouble(i));
224  if(aux_val <= initVal)
225  initVal = aux_val;
226  }
227  break;
229  {
230  aux_val = boost::lexical_cast<double>(dsQuery->getNumeric(i));
231  if(aux_val <= initVal)
232  initVal = aux_val;
233  }
234  break;
235  default:
236  break;
237  }
238  }
239  if(vecProps[i]->getName() == m_finalLeft || vecProps[i]->getName() == m_finalRight)
240  {
241  int type = vecProps[i]->getType();
242 
243  switch (type)
244  {
245  case te::dt::INT16_TYPE:
246  {
247  aux_val = dsQuery->getInt16(i);
248  if(aux_val >= finalVal)
249  finalVal = aux_val;
250  }
251  break;
252  case te::dt::INT32_TYPE:
253  {
254  aux_val = dsQuery->getInt32(i);
255  if(aux_val >= finalVal)
256  finalVal = aux_val;
257  }
258  break;
259  case te::dt::INT64_TYPE:
260  {
261  aux_val = boost::lexical_cast<double>(dsQuery->getInt64(i));
262  if(aux_val >= finalVal)
263  finalVal = aux_val;
264  }
265  break;
266  case te::dt::DOUBLE_TYPE:
267  {
268  aux_val = boost::lexical_cast<double>(dsQuery->getDouble(i));
269  if(aux_val >= finalVal)
270  finalVal = aux_val;
271  }
272  break;
274  {
275  aux_val = boost::lexical_cast<double>(dsQuery->getNumeric(i).c_str());
276  if(aux_val >= finalVal)
277  finalVal = aux_val;
278  }
279  break;
280  default:
281  break;
282  }
283  }
284  }
285  else if (vecProps[i]->getType() == te::dt::GEOMETRY_TYPE)
286  {
287  geomPos = i;
288  }
289  }
290 
291  std::auto_ptr<te::gm::Geometry> geom = dsQuery->getGeometry(geomPos);
292 
293  te::gm::LineString* lineString = getLineString(geom.get());
294 
295  if(!lineString)
296  continue;
297 
298  int numTarget = boost::lexical_cast<int>(dsAddress->getDouble(m_streetNumber));
299 
300  te::gm::Coord2D* target = te::gm::locateAlong(lineString, initVal, finalVal, numTarget);
301  te::gm::Point* point = new te::gm::Point(target->getX(), target->getY(), m_inSRID);
302  itemMemory->setValue(geomPos, point);
303 
304  dataSetMemory->add(itemMemory);
305  }
306  else
307  {
308  //Address not found.
309  }
310 
311  }
312 
313  // save the result
314  return save(dataSetMemory,outDsType);
315 }
316 
317 bool te::addressgeocoding::AddressGeocodingOp::save(std::auto_ptr<te::mem::DataSet> result, std::auto_ptr<te::da::DataSetType> outDsType)
318 {
319  // do any adaptation necessary to persist the output dataset
320  te::da::DataSetTypeConverter* converter = new te::da::DataSetTypeConverter(outDsType.get(), m_outDsrc->getCapabilities());
321  te::da::DataSetType* dsTypeResult = converter->getResult();
322  std::auto_ptr<te::da::DataSetAdapter> dsAdapter(te::da::CreateAdapter(result.get(), converter));
323 
324  std::map<std::string, std::string> options;
325  // create the dataset
326  m_outDsrc->createDataSet(dsTypeResult, options);
327 
328  // copy from memory to output datasource
329  result->moveBeforeFirst();
330  m_outDsrc->add(dsTypeResult->getName(),result.get(), options);
331 
332  // create the primary key if it is possible
333  if (m_outDsrc->getCapabilities().getDataSetTypeCapabilities().supportsPrimaryKey())
334  {
335  std::string pk_name = dsTypeResult->getName() + "_pkey";
336  te::da::PrimaryKey* pk = new te::da::PrimaryKey(pk_name, dsTypeResult);
337  pk->add(dsTypeResult->getProperty(0));
338  m_outDsrc->addPrimaryKey(m_outDsetName,pk);
339  }
340 
341  return true;
342 }
343 
345 {
346  std::auto_ptr<te::da::DataSetType> inDsType = m_inDsrc->getDataSetType(m_inDsetName);
347  std::auto_ptr<te::da::DataSetType> outDsType(new te::da::DataSetType(m_outDsetName));
348 
349  std::vector<te::dt::Property*> vecProps = inDsType->getProperties();
350 
351  for(std::size_t i = 0; i < vecProps.size(); ++i)
352  {
353  if(vecProps[i]->getType() != te::dt::GEOMETRY_TYPE && vecProps[i]->getName() != "tsvector")
354  {
355  outDsType->add(vecProps[i]->clone());
356  }
357  else if(vecProps[i]->getType() == te::dt::GEOMETRY_TYPE)
358  {
359  te::gm::GeometryProperty* p = dynamic_cast<te::gm::GeometryProperty*>(vecProps[i]);
360 
361  te::gm::GeometryProperty* geometry = new te::gm::GeometryProperty("geom");
363  geometry->setSRID(p->getSRID());
364 
365  outDsType->add(geometry);
366  }
367  }
368 
369  return outDsType;
370 }
371 
373 {
374  te::gm::LineString* line = 0;
375  std::vector<te::gm::LineString*> vecLines;
376 
377  getLines(geom, vecLines);
378 
379  if(vecLines.size() > 0)
380  line = vecLines[0];
381 
382  for(std::size_t i = 1; i < vecLines.size(); ++i)
383  line->Union(vecLines[i]);
384 
385  return line;
386 }
387 
388 void te::addressgeocoding::AddressGeocodingOp::getLines(te::gm::Geometry* geom, std::vector<te::gm::LineString*>& lines)
389 {
390  if(geom == 0)
391  return;
392 
393  switch(geom->getGeomTypeId())
394  {
396  getLines(dynamic_cast<te::gm::GeometryCollection*>(geom), lines);
397  break;
398 
400  getLines(dynamic_cast<te::gm::LineString*>(geom), lines);
401  break;
402 
403  default:
404  return;
405  }
406 }
407 
408 void te::addressgeocoding::AddressGeocodingOp::getLines(te::gm::GeometryCollection* gc, std::vector<te::gm::LineString*>& lines)
409 {
410  assert(gc);
411 
412  for(std::size_t i = 0; i < gc->getNumGeometries(); ++i)
413  getLines(gc->getGeometryN(i), lines);
414 }
415 
416 void te::addressgeocoding::AddressGeocodingOp::getLines(te::gm::LineString* l, std::vector<te::gm::LineString*>& lines)
417 {
418  assert(l);
419  lines.push_back(l);
420 }
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.
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.
TECOMMONEXPORT std::string ReplaceSpecialChars(const std::string &str, bool &changed)
It replace special characters of a string.
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