FlowGraphBuilder.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 terralib/graph/FlowGraphBuilder.cpp
22 
23  \brief This class defines the Flow strategy to build a graph.
24 
25  This function needs a vectorial data and table with flow information,
26  this table must have the origin and destination info about each flow.
27 
28 */
29 
30 // TerraLib Includes
31 #include "../../common/StringUtils.h"
32 #include "../../core/translator/Translator.h"
33 #include "../../dataaccess/datasource/DataSource.h"
34 #include "../../dataaccess/datasource/DataSourceFactory.h"
35 #include "../../dataaccess/dataset/DataSet.h"
36 #include "../../datatype/AbstractData.h"
37 #include "../../datatype/SimpleData.h"
38 #include "../../datatype/SimpleProperty.h"
39 #include "../../geometry/GeometryProperty.h"
40 #include "../../geometry/MultiPolygon.h"
41 #include "../../geometry/Point.h"
42 #include "../../geometry/Polygon.h"
43 #include "../core/AbstractGraphFactory.h"
44 #include "../core/Edge.h"
45 #include "../core/Vertex.h"
46 #include "../core/VertexProperty.h"
47 #include "../graphs/Graph.h"
48 #include "../Config.h"
49 #include "../Exception.h"
50 #include "FlowGraphBuilder.h"
51 
52 // STL Includes
53 #include <fstream>
54 #include <iosfwd>
55 
56 // BOOST Includes
57 #include<boost/tokenizer.hpp>
58 
59 
61 {
62  m_edgeId = 0;
63 }
64 
66 
67 bool te::graph::FlowGraphBuilder::build(const std::string& shapeFileName, const std::string& linkColumn, const int& srid, const std::string& csvFileName, const int& fromIdx, const int& toIdx, const int& weightIdx,
68  const std::string& dsInfo, const std::string& graphType, const std::map<std::string, std::string>& gInfo)
69 {
70  //create output graph
71  m_graph.reset(te::graph::AbstractGraphFactory::make(graphType, dsInfo, gInfo));
72 
73  assert(m_graph);
74 
75  if(createVertexObjects(shapeFileName, linkColumn, srid) == false)
76  {
77  return false;
78  }
79 
80  if(createEdgeObjects(csvFileName, fromIdx, toIdx, weightIdx) == false)
81  {
82  return false;
83  }
84 
85  return true;
86 }
87 
89 {
90  int id = m_edgeId;
91 
92  m_edgeId++;
93 
94  return id;
95 }
96 
97 std::unique_ptr<te::da::DataSource> te::graph::FlowGraphBuilder::getDataSource(const std::string fileName)
98 {
99  // Creates and connects data source
100  std::unique_ptr<te::da::DataSource> ds = te::da::DataSourceFactory::make("OGR", ("file://" + fileName));
101  ds->open();
102 
103  return ds;
104 }
105 
107 {
108  std::vector<std::string> names = ds->getDataSetNames();
109 
110  std::string dsName = names[0];
111 
112  std::unique_ptr<te::da::DataSet> dataset = ds->getDataSet(dsName);
113 
114  return dataset;
115 }
116 
118 {
119  std::vector<std::string> names = ds->getDataSetNames();
120 
121  std::string dsName = names[0];
122 
123  return ds->getProperties(dsName);
124 }
125 
126 bool te::graph::FlowGraphBuilder::createVertexObjects(const std::string& shapeFileName, const std::string& linkColumn, const int& srid)
127 {
128  //get data source
129  std::unique_ptr<te::da::DataSource> ds = getDataSource(shapeFileName);
130 
131  if(ds.get() == nullptr)
132  {
133  return false;
134  }
135 
136  //get data set
137  std::unique_ptr<te::da::DataSet> dataSet = getDataSet(ds.get());
138 
139  if(dataSet.get() == nullptr)
140  {
141  return false;
142  }
143 
144  //get properties
145  boost::ptr_vector<te::dt::Property> properties = getProperties(ds.get());
146 
147  if(properties.empty())
148  {
149  return false;
150  }
151 
152 //create graph vertex attrs
153  boost::ptr_vector<te::dt::Property>::iterator it = properties.begin();
154 
155  int count = 0;
156 
157  while(it != properties.end())
158  {
159  if(te::common::Convert2UCase(it->getName()) == te::common::Convert2UCase(linkColumn))
160  {
161  ++it;
162  continue;
163  }
164 
166 
167  if(it->getType() == te::dt::GEOMETRY_TYPE)
168  {
169  //create graph attrs
170  te::gm::GeometryProperty* gProp = new te::gm::GeometryProperty("coords");
171  gProp->setId(0);
173  gProp->setSRID(srid);
174 
175  p = gProp;
176  }
177  else
178  {
179  p = it->clone();
180  p->setParent(nullptr);
181  p->setId(count);
182  }
183 
184  m_graph->addVertexProperty(p);
185 
186  ++count;
187 
188  ++it;
189  }
190 
191  //create vertex objects
192  while(dataSet->moveNext())
193  {
194  int id = dataSet->getInt32(linkColumn);
195 
196  Vertex* v = new Vertex(id);
197 
198  v->setAttributeVecSize((int)properties.size() - 1);
199 
200  int shift = 0;
201 
202  it = properties.begin();
203 
204  count = 0;
205 
206  while(it != properties.end())
207  {
208  if(te::common::Convert2UCase(it->getName()) == te::common::Convert2UCase(linkColumn))
209  {
210  shift = 1;
211  ++it;
212  continue;
213  }
214 
215  te::dt::AbstractData* ad = nullptr;
216 
217  if(it->getType() == te::dt::GEOMETRY_TYPE)
218  {
219  te::gm::Geometry* g = dataSet->getGeometry(it->getName()).release();
220  g->setSRID(srid);
221 
222  if(g->getGeomTypeId() == te::gm::PointType)
223  {
224  ad = g;
225  }
226  else if(g->getGeomTypeId() == te::gm::PolygonType)
227  {
229  p->setSRID(srid);
230 
231  ad = p;
232  }
233  else if(g->getGeomTypeId() == te::gm::MultiPolygonType)
234  {
235  te::gm::Polygon* poly = (te::gm::Polygon*)((te::gm::MultiPolygon*)g)->getGeometryN(0);
236 
237  te::gm::Point* p = poly->getCentroid();
238  p->setSRID(srid);
239 
240  ad = p;
241  }
242  }
243  else
244  {
245  ad = dataSet->getValue(it->getName()).release();
246  }
247 
248  v->addAttribute(count - shift, ad);
249 
250  ++ count;
251 
252  ++it;
253  }
254 
255  m_graph->add(v);
256  }
257 
258  return true;
259 }
260 
261 bool te::graph::FlowGraphBuilder::createEdgeObjects(const std::string& csvFileName, const int& fromIdx, const int& toIdx, const int& weightIdx)
262 {
263  //open file
264  std::ifstream in(csvFileName.c_str());
265 
266  if(in.is_open() == false)
267  {
268  return false;
269  }
270 
272  p->setParent(nullptr);
273  p->setId(0);
274 
275  m_graph->addEdgeProperty(p);
276 
277  //create boost tokenizer
278  typedef boost::tokenizer< boost::escaped_list_separator<char> > Tokenizer;
279  boost::escaped_list_separator<char> sep('\\', ';', '\"');
280 
281  std::vector<std::string> line;
282  std::string buffer;
283 
284  //access each line of the csv file
285  while(std::getline(in, buffer))
286  {
287  line.clear();
288 
289  Tokenizer tok(buffer, sep);
290 
291  line.assign(tok.begin(), tok.end());
292 
293  std::string fromStr, toStr, weightStr;
294  try
295  {
296  fromStr = line[fromIdx];
297  toStr = line[toIdx];
298  weightStr = line[weightIdx];
299  }
300  catch(...)
301  {
302  return false;
303  }
304 
305  //create edge
306  int id = getEdgeId();
307  int from = atoi(fromStr.c_str());
308  int to = atoi(toStr.c_str());
309  int weight = atoi(weightStr.c_str());
310 
311  Edge* e = new Edge(id, from, to);
312 
313  e->setAttributeVecSize(1); //weight attribute
314  e->addAttribute(0, new te::dt::SimpleData<int, te::dt::INT32_TYPE>(weight));
315 
316  m_graph->add(e);
317  }
318 
319  return true;
320 }
FlowGraphBuilder()
Default constructor.
MultiPolygon is a MultiSurface whose elements are Polygons.
Definition: MultiPolygon.h:50
void setAttributeVecSize(int size)
This function is used to set the number of attributes associated with the vertex elements.
Definition: Vertex.cpp:79
static std::unique_ptr< DataSource > make(const std::string &driver, const te::core::URI &connInfo)
Geometric property.
void setSRID(int srid)
It sets the spatial reference system identifier associated to this property.
void setGeometryType(GeomType t)
It sets the geometry subtype.
void setSRID(int srid) _NOEXCEPT_OP(true)
It sets the Spatial Reference System ID of the Point.
An atomic property like an integer or double.
virtual boost::ptr_vector< te::dt::Property > getProperties(const std::string &datasetName)
It retrieves the properties of the dataset.
virtual ~FlowGraphBuilder()
Virtual destructor.
GeomType getGeomTypeId() const _NOEXCEPT_OP(true)
It returns the geometry subclass type identifier.
int m_edgeId
Attribute used as a index counter for edge objects.
std::string Convert2UCase(const std::string &value)
It converts a string to upper case.
Definition: StringUtils.h:168
static te::dt::Date ds(2010, 01, 01)
An abstract class for data providers like a DBMS, Web Services or a regular file. ...
virtual Property * clone() const =0
It returns a clone of the object.
It models a property definition.
Definition: Property.h:59
From the point of view of graph theory, vertices are treated as featureless and indivisible objects...
Definition: Vertex.h:68
void setId(unsigned int id)
It sets the property identifier.
Definition: Property.h:118
unsigned int line
Class used to define the edge struct of a graph. Its compose with a identifier, the vertex origin and...
Definition: Edge.h:58
std::unique_ptr< te::da::DataSet > getDataSet(te::da::DataSource *ds)
Function used to get the data set with the vectorial data.
A point with x and y coordinate values.
Definition: Point.h:50
bool build(const std::string &shapeFileName, const std::string &linkColumn, const int &srid, const std::string &csvFileName, const int &fromIdx, const int &toIdx, const int &weightIdx, const std::string &dsInfo, const std::string &graphType, const std::map< std::string, std::string > &gInfo)
Function used to build the output graph based on input parameters.
te::gm::Polygon * p
std::unique_ptr< te::da::DataSource > getDataSource(const std::string fileName)
Function used to get the data source with the vectorial data.
A base class for values that can be retrieved from the data access module.
Definition: AbstractData.h:57
virtual std::vector< std::string > getDataSetNames()
It gets the dataset names available in the data source.
Geometry is the root class of the geometries hierarchy, it follows OGC and ISO standards.
boost::ptr_vector< te::dt::Property > getProperties(te::da::DataSource *ds)
Function used to get the data source properties.
virtual std::unique_ptr< DataSet > getDataSet(const std::string &name, te::common::TraverseType travType=te::common::FORWARDONLY, const te::common::AccessPolicy accessPolicy=te::common::RAccess)
It gets the dataset identified by the given name. This method always returns a disconnected dataset...
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
Definition: Polygon.h:50
bool createEdgeObjects(const std::string &csvFileName, const int &fromIdx, const int &toIdx, const int &weightIdx)
Function used to create all edges object based on flow table data.
virtual void setSRID(int srid) _NOEXCEPT_OP(true)=0
It sets the Spatial Reference System ID of the geometry and all its parts if it is a GeometryCollecti...
Point * getCentroid() const
It returns the mathematical centroid for this surface as a point.
int getEdgeId()
Function used to generated the edge id.
bool createVertexObjects(const std::string &shapeFileName, const std::string &linkColumn, const int &srid)
Function used to create all vertex object based on vectorial data.
void addAttribute(int idx, te::dt::AbstractData *ad)
Add a new attribute to this element.
Definition: Vertex.cpp:84
boost::shared_ptr< AbstractGraph > m_graph
Graph object.
A template for atomic data types (integers, floats, strings and others).
Definition: SimpleData.h:59
static AbstractGraph * make()
It creates and returns an empty graph with default graph type.
void setParent(Property *p)
It associate this property to the informed parent.
Definition: Property.h:177