All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
SpatialWeightsExchanger.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 SpatialWeightsExchanger.cpp
22 
23  \brief This class defines functions used to load and save graphs using GAL and GWT formats,
24  both formats use a ' ' as separator.
25 
26  GAL FORMAT
27 
28  0 NUMBER_OBSERVATIONS DATASET_NAME ATTRIBUTE_ID_NAME (HEADER LINE)
29  OBSERVATION_ID NUMBER_NEIGHBOURS
30  NEIGHBOURS_1 NEIGHBOURS_2 ... NEIGHBOURS_N
31  OBSERVATION_ID NUMBER_NEIGHBOURS
32  NEIGHBOURS_1 NEIGHBOURS_2 ... NEIGHBOURS_N
33  ...
34 
35 
36  GWT FORMAT
37 
38  0 NUMBER_OBSERVATIONS DATASET_NAME ATTRIBUTE_ID_NAME (HEADER LINE)
39  OBSERVATION_ID_FROM OBSERVATION_ID_TO DISTANCE
40  OBSERVATION_ID_FROM OBSERVATION_ID_TO DISTANCE
41  OBSERVATION_ID_FROM OBSERVATION_ID_TO DISTANCE
42  ...
43 */
44 
45 //Terralib Includes
46 #include "../../common/Exception.h"
47 #include "../../common/Translator.h"
48 #include "../../common/progress/TaskProgress.h"
49 #include "../../dataaccess/datasource/DataSource.h"
50 #include "../../dataaccess/utils/Utils.h"
51 #include "../../datatype/SimpleData.h"
52 #include "../../datatype/SimpleProperty.h"
53 #include "../../geometry/GeometryProperty.h"
54 #include "../../geometry/MultiPolygon.h"
55 #include "../../geometry/Point.h"
56 #include "../../geometry/Polygon.h"
57 #include "../../graph/core/AbstractGraph.h"
58 #include "../../graph/core/AbstractGraphFactory.h"
59 #include "../../graph/core/GraphMetadata.h"
60 #include "../../graph/core/Edge.h"
61 #include "../../graph/core/Vertex.h"
62 #include "../../graph/iterator/AbstractIterator.h"
63 #include "../../graph/iterator/SequenceIterator.h"
64 #include "../../graph/iterator/MemoryIterator.h"
65 #include "../../graph/Globals.h"
68 
69 //STL Includes
70 #include <cassert>
71 #include <fstream>
72 #include <iosfwd>
73 #include <stdio.h>
74 
75 // BOOST Includes
76 #include<boost/tokenizer.hpp>
77 
79 {
80 }
81 
83 {
84 }
85 
87 {
88  //get iterator
89  std::auto_ptr<te::graph::AbstractIterator> it;
90 
92 
93  if(g->getMetadata()->getDataSource())
94  {
95  it.reset(new te::graph::SequenceIterator(g));
96  }
97  else
98  {
99  it.reset(new te::graph::MemoryIterator(g));
100  }
101 
102  assert(it.get());
103 
104  //create file
105  FILE* fp = fopen(pathFileName.c_str(), "w");
106 
107  assert(fp);
108 
109  //write header info
110  if(gpm->getDataSetName().empty())
111  {
112  fprintf(fp, "%d\n", (int)it->getVertexInteratorCount());
113  }
114  else
115  {
116  fprintf(fp, "0 %d %s %s\n", (int)it->getVertexInteratorCount(), gpm->getDataSetName().c_str(), gpm->getAttributeName().c_str());
117  }
118 
119  //create task
121 
122  task.setTotalSteps(it->getVertexInteratorCount());
123  task.setMessage(TE_TR("Export to GAL Format."));
124 
125  //write body info
126  te::graph::Vertex* v = it->getFirstVertex();
127 
128  while(it->isVertexIteratorAfterEnd() == false)
129  {
130  int id = v->getId();
131  std::set<int> neighbours = v->getSuccessors();
132  std::set<int>::iterator itNeighbours = neighbours.begin();
133 
134  if(!neighbours.empty())
135  {
136  fprintf(fp, "%d %d\n", id, (int)neighbours.size());
137 
138  while(itNeighbours != neighbours.end())
139  {
140  te::graph::Edge* e = g->getEdge(*itNeighbours);
141 
142  if(e)
143  {
144  if(e->getIdFrom() == id)
145  fprintf (fp, "%d ", e->getIdTo());
146  else
147  fprintf (fp, "%d ", e->getIdFrom());
148  }
149 
150  ++itNeighbours;
151  }
152 
153  fprintf (fp, "\n");
154  }
155 
156  if(!task.isActive())
157  {
158  fclose(fp);
159 
160  throw te::common::Exception(TE_TR("Operation canceled by the user."));
161  }
162 
163  task.pulse();
164 
165  v = it->getNextVertex();
166  }
167 
168  fclose(fp);
169 }
170 
172 {
173  //open file
174  std::ifstream file(pathFileName.c_str());
175 
176  if(file.is_open() == false)
177  return 0;
178 
179  int count = (int)std::count(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), '\n');
180 
181  file.clear();
182  file.seekg(0, std::ios::beg);
183 
184  //create output gpm
186 
187  // graph type
189 
190  // connection info
191  std::map<std::string, std::string> connInfo;
192 
193  // graph information
194  std::map<std::string, std::string> graphInfo;
195  graphInfo["GRAPH_DATA_SOURCE_TYPE"] = "MEM";
196  graphInfo["GRAPH_NAME"] = "gpm_gal_graph";
197  graphInfo["GRAPH_DESCRIPTION"] = "Generated by Spatial Weights Exchanger.";
198 
199  //create output graph
200  gpm->setGraph(te::graph::AbstractGraphFactory::make(graphType, connInfo, graphInfo));
201 
202  te::graph::AbstractGraph* graph = gpm->getGraph();
203  assert(graph);
204 
205  //create boost tokenizer
206  typedef boost::tokenizer< boost::escaped_list_separator<char> > Tokenizer;
207  boost::escaped_list_separator<char> sep('\\', ' ', '\"');
208 
209  std::vector<std::string> line;
210  std::string buffer;
211 
212  //get header line
213  std::getline(file, buffer);
214  Tokenizer tok(buffer, sep);
215  line.assign(tok.begin(), tok.end());
216 
217  std::string dataSetName = "";
218  std::string attributeName = "";
219  bool associateGeom = false;
220 
221  if(line.size() == 4 && ds) // has the number of observations and data set information
222  {
223  associateGeom = true;
224 
225  dataSetName = line[2];
226  attributeName = line[3];
227 
228  gpm->setDataSetName(dataSetName);
229  gpm->setAttributeName(attributeName);
230  }
231 
232  //create task
234 
235  task.setTotalSteps(count);
236  task.setMessage(TE_TR("Import from GAL Format."));
237 
238  //access each line of the gat file
239  m_edgeId = 0;
240 
241  while(std::getline(file, buffer))
242  {
243  line.clear();
244  Tokenizer tok(buffer, sep);
245  line.assign(tok.begin(), tok.end());
246 
247  std::string vertexIdStr, nNeighboursStr;
248 
249  try
250  {
251  vertexIdStr = line[0];
252  nNeighboursStr = line[1];
253  }
254  catch(...)
255  {
256  delete graph;
257 
258  return 0;
259  }
260 
261  //create vertex
262  int vId = atoi(vertexIdStr.c_str());
263  te::graph::Vertex* v = graph->getVertex(vId);
264 
265  if(!v)
266  {
267  v = new te::graph::Vertex(vId);
268  graph->add(v);
269  }
270 
271  //get new line in gal file
272  std::getline(file, buffer);
273  line.clear();
274  Tokenizer tok2(buffer, sep);
275  line.assign(tok2.begin(), tok2.end());
276 
277  //get neighbours
278  int nNeighbours = atoi(nNeighboursStr.c_str());
279 
280  try
281  {
282  for(int i = 0; i < nNeighbours; ++i)
283  {
284  std::string vNeighbourStr = line[i];
285  int vNeighbourId = atoi(vNeighbourStr.c_str());
286 
287  //add vertex neighbour
288  te::graph::Vertex* vNeighbour = graph->getVertex(vNeighbourId);
289 
290  if(!vNeighbour)
291  {
292  vNeighbour = new te::graph::Vertex(vNeighbourId);
293  graph->add(vNeighbour);
294  }
295 
296  //create edge
297  int id = getEdgeId();
298 
299  te::graph::Edge* e = new te::graph::Edge(id, vId, vNeighbourId);
300  graph->add(e);
301  }
302  }
303  catch(...)
304  {
305  delete graph;
306 
307  return 0;
308  }
309 
310  if(!task.isActive())
311  {
312  file.close();
313 
314  throw te::common::Exception(TE_TR("Operation canceled by the user."));
315  }
316 
317  task.pulse();
318  }
319 
320  file.close();
321 
322  if(associateGeom)
323  associateGeometry(gpm, ds);
324 
325  return gpm;
326 }
327 
328 void te::sa::SpatialWeightsExchanger::exportToGWT(te::sa::GeneralizedProximityMatrix* gpm, std::string pathFileName, int distAttrIdx)
329 {
331 
332  //get iterator
333  std::auto_ptr<te::graph::AbstractIterator> it;
334 
335  if(g->getMetadata()->getDataSource())
336  {
337  it.reset(new te::graph::SequenceIterator(g));
338  }
339  else
340  {
341  it.reset(new te::graph::MemoryIterator(g));
342  }
343 
344  assert(it.get());
345 
346  //create file
347  FILE* fp = fopen(pathFileName.c_str(), "w");
348 
349  assert(fp);
350 
351  //write header info
352  if(gpm->getDataSetName().empty())
353  {
354  fprintf(fp, "%d\n", (int)it->getEdgeInteratorCount());
355  }
356  else
357  {
358  fprintf(fp, "0 %d %s %s\n", (int)it->getEdgeInteratorCount(), gpm->getDataSetName().c_str(), gpm->getAttributeName().c_str());
359  }
360 
361  //create task
363 
364  task.setTotalSteps(it->getVertexInteratorCount());
365  task.setMessage(TE_TR("Export to GWT Format."));
366 
367  //write body info
368  te::graph::Edge* e = it->getFirstEdge();
369 
370  while(it->isEdgeIteratorAfterEnd() == false)
371  {
372  int idFrom = e->getIdFrom();
373  int idTo = e->getIdTo();
374 
376 
377  double distance = sd->getValue();
378 
379  fprintf(fp, "%d %d %3.7f\n", idFrom, idTo, distance);
380 
381  if(!task.isActive())
382  {
383  fclose(fp);
384 
385  throw te::common::Exception(TE_TR("Operation canceled by the user."));
386  }
387 
388  task.pulse();
389 
390  e = it->getNextEdge();
391  }
392 
393  fclose(fp);
394 }
395 
397 {
398  //open file
399  std::ifstream file(pathFileName.c_str());
400 
401  if(file.is_open() == false)
402  return 0;
403 
404  int count = (int)std::count(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(), '\n');
405 
406  file.clear();
407  file.seekg(0, std::ios::beg);
408 
409  //create output gpm
411 
412  // graph type
414 
415  // connection info
416  std::map<std::string, std::string> connInfo;
417 
418  // graph information
419  std::map<std::string, std::string> graphInfo;
420  graphInfo["GRAPH_DATA_SOURCE_TYPE"] = "MEM";
421  graphInfo["GRAPH_NAME"] = "gpm_gwt_graph";
422  graphInfo["GRAPH_DESCRIPTION"] = "Generated by Spatial Weights Exchanger.";
423 
424  //create output graph
425  gpm->setGraph(te::graph::AbstractGraphFactory::make(graphType, connInfo, graphInfo));
426 
427  te::graph::AbstractGraph* graph = gpm->getGraph();
428  assert(graph);
429 
430  //add edge property
432  p->setParent(0);
433  p->setId(0);
434 
435  graph->addEdgeProperty(p);
436 
437  //create boost tokenizer
438  typedef boost::tokenizer< boost::escaped_list_separator<char> > Tokenizer;
439  boost::escaped_list_separator<char> sep('\\', ' ', '\"');
440 
441  std::vector<std::string> line;
442  std::string buffer;
443 
444  //get header line
445  std::getline(file, buffer);
446  Tokenizer tok(buffer, sep);
447  line.assign(tok.begin(), tok.end());
448 
449  std::string dataSetName = "";
450  std::string attributeName = "";
451  bool associateGeom = false;
452 
453  if(line.size() == 4 && ds) // has the number of observations and data set information
454  {
455  associateGeom = true;
456 
457  dataSetName = line[2];
458  attributeName = line[3];
459 
460  gpm->setDataSetName(dataSetName);
461  gpm->setAttributeName(attributeName);
462  }
463 
464  //create task
466 
467  task.setTotalSteps(count);
468  task.setMessage(TE_TR("Import from GWT Format."));
469 
470  //access each line of the gwt file
471  m_edgeId = 0;
472 
473  while(std::getline(file, buffer))
474  {
475  line.clear();
476 
477  Tokenizer tok(buffer, sep);
478 
479  line.assign(tok.begin(), tok.end());
480 
481  std::string fromStr, toStr, distanceStr;
482 
483  try
484  {
485  fromStr = line[0];
486  toStr = line[1];
487  distanceStr = line[2];
488  }
489  catch(...)
490  {
491  delete graph;
492 
493  return 0;
494  }
495 
496  //create vertex from
497  int from = atoi(fromStr.c_str());
498 
499  te::graph::Vertex* vFrom = graph->getVertex(from);
500 
501  if(!vFrom)
502  {
503  vFrom = new te::graph::Vertex(from);
504  graph->add(vFrom);
505  }
506 
507  //create vertex to
508  int to = atoi(toStr.c_str());
509 
510  te::graph::Vertex* vTo = graph->getVertex(to);
511 
512  if(!vTo)
513  {
514  vTo = new te::graph::Vertex(to);
515  graph->add(vTo);
516  }
517 
518  //create edge
519  int id = getEdgeId();
520  double distance = atof(distanceStr.c_str());
521 
522  te::graph::Edge* e = new te::graph::Edge(id, from, to);
523  e->setAttributeVecSize(1); //distance attribute
524  e->addAttribute(0, new te::dt::SimpleData<double, te::dt::DOUBLE_TYPE>(distance));
525 
526  graph->add(e);
527 
528  if(!task.isActive())
529  {
530  file.close();
531 
532  throw te::common::Exception(TE_TR("Operation canceled by the user."));
533  }
534 
535  task.pulse();
536  }
537 
538  file.close();
539 
540  if(associateGeom)
541  associateGeometry(gpm, ds);
542 
543  return gpm;
544 }
545 
546 void te::sa::SpatialWeightsExchanger::getSpatialWeightsFileInfo(std::string pathFileName, std::string& dataSetName, std::string& attrName)
547 {
548  //open file
549  std::ifstream file(pathFileName.c_str());
550 
551  if(file.is_open() == false)
552  return;
553 
554  //create boost tokenizer
555  typedef boost::tokenizer< boost::escaped_list_separator<char> > Tokenizer;
556  boost::escaped_list_separator<char> sep('\\', ' ', '\"');
557 
558  std::vector<std::string> line;
559  std::string buffer;
560 
561  //get header line
562  std::getline(file, buffer);
563  Tokenizer tok(buffer, sep);
564  line.assign(tok.begin(), tok.end());
565 
566  if(line.size() == 4) // has the number of observations and data set information
567  {
568  dataSetName = line[2];
569  attrName = line[3];
570  }
571 }
572 
574 {
575  int id = m_edgeId;
576 
577  m_edgeId++;
578 
579  return id;
580 }
581 
583 {
584  //get srid information
585  std::auto_ptr<te::da::DataSetType> dataSetType = ds->getDataSetType(gpm->getDataSetName());
587 
588  //create graph vertex attrs
590  gProp->setId(0);
591  gProp->setGeometryType(te::gm::PointType);
592  gProp->setSRID(gp->getSRID());
593 
595 
596  g->addVertexProperty(gProp);
597 
598  //get data set
599  std::auto_ptr<te::da::DataSet> dataSet = ds->getDataSet(gpm->getDataSetName());
600 
601  std::size_t geomPos = te::da::GetFirstSpatialPropertyPos(dataSet.get());
602 
603  //create task
605 
606  task.setTotalSteps(dataSet->size());
607  task.setMessage(TE_TR("Associating Geometry to graph."));
608 
609  dataSet->moveBeforeFirst();
610 
611  while(dataSet->moveNext())
612  {
613  std::string strId = dataSet->getAsString(gpm->getAttributeName());
614 
615  int id = atoi(strId.c_str());
616 
617  te::graph::Vertex* v = g->getVertex(id);
618 
619  if(v)
620  {
621  v->setAttributeVecSize(1);
622 
623  std::auto_ptr<te::gm::Geometry> g = dataSet->getGeometry(geomPos);
624 
625  te::dt::AbstractData* ad = 0;
626 
627  if(g->getGeomTypeId() == te::gm::PointType)
628  {
629  g->setSRID(gp->getSRID());
630 
631  ad = g->clone();
632  }
633  else if(g->getGeomTypeId() == te::gm::PolygonType)
634  {
635  te::gm::Point* p = ((te::gm::Polygon*)g.get())->getCentroid();
636  p->setSRID(gp->getSRID());
637 
638  ad = p;
639  }
640  else if(g->getGeomTypeId() == te::gm::MultiPolygonType)
641  {
642  te::gm::Polygon* poly = (te::gm::Polygon*)((te::gm::MultiPolygon*)g.get())->getGeometryN(0);
643 
644  te::gm::Point* p = poly->getCentroid();
645  p->setSRID(gp->getSRID());
646 
647  ad = p;
648  }
649 
650  v->addAttribute(0, ad);
651 
652  v->setDirty(true);
653  }
654 
655  if(!task.isActive())
656  {
657  throw te::common::Exception(TE_TR("Operation canceled by the user."));
658  }
659 
660  task.pulse();
661  }
662 }
te::da::DataSource * getDataSource()
It returns the data source associated with this graph.
MultiPolygon is a MultiSurface whose elements are Polygons.
Definition: MultiPolygon.h:50
#define TE_SA_GEOMETRY_ATTR_NAME
Definition: Config.h:44
void setAttributeVecSize(int size)
This function is used to set the number of attributes associated with the vertex elements.
Definition: Vertex.cpp:79
void exportToGWT(te::sa::GeneralizedProximityMatrix *gpm, std::string pathFileName, int distAttrIdx)
Function used to export a gpm to Spatial Weights File GWT Format.
Geometric property.
void setMessage(const std::string &message)
Set the task message.
void associateGeometry(te::sa::GeneralizedProximityMatrix *gpm, te::da::DataSource *ds)
Function used to associate the geometry coord attribute to vertex objects.
An atomic property like an integer or double.
This class defines a Generalized Proximity Matrix.
virtual te::graph::Edge * getEdge(int id)=0
It returns the edge element if it's exist.
virtual void addEdgeProperty(te::dt::Property *p)=0
Add a new property associated to the edge element.
This class can be used to inform the progress of a task.
Definition: TaskProgress.h:53
int getEdgeId()
Function used to generated the edge id.
T getValue() const
It returns the associated value.
Definition: SimpleData.h:139
te::sa::GeneralizedProximityMatrix * importFromGAL(std::string pathFileName, te::da::DataSource *ds=0)
Function used to import a gpm from a Spatial Weights File GAL Format.
An abstract class for data providers like a DBMS, Web Services or a regular file. ...
Definition: DataSource.h:118
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:347
This class defines functions used to load and save gpm's using GAL and GWT formats, both formats use a ' ' as separator.
te::sa::GeneralizedProximityMatrix * importFromGWT(std::string pathFileName, te::da::DataSource *ds=0)
Function used to import a gpm from a Spatial Weights File GWT Format.
virtual void add(Vertex *v)=0
Add a new vertex element to a graph.
bool isActive() const
Verify if the task is active.
From the point of view of graph theory, vertices are treated as featureless and indivisible objects...
Definition: Vertex.h:68
void setTotalSteps(int value)
Set the task total stepes.
void setId(unsigned int id)
It sets the property identifier.
Definition: Property.h:118
virtual te::graph::GraphMetadata * getMetadata()=0
Function used to access the graph metadata.
Class used to define the edge struct of a graph. Its compose with a identifier, the vertex origin and...
Definition: Edge.h:58
void setDataSetName(const std::string &dataSetName)
SpatialWeightsExchanger()
Default constructor.
TEDATAACCESSEXPORT std::size_t GetFirstSpatialPropertyPos(const te::da::DataSet *dataset)
It returns the first dataset spatial property or NULL if none is found.
Definition: Utils.cpp:462
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
#define TE_SA_WEIGHT_ATTR_NAME
Definition: Config.h:41
void setSRID(int srid)
It sets the Spatial Reference System ID of the Point.
virtual void addVertexProperty(te::dt::Property *p)=0
Add a new property associated to the vertex element.
Abstract class used to define the main functions of graph struct. All graph implementations must used...
Definition: AbstractGraph.h:55
virtual std::auto_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...
Definition: DataSource.cpp:61
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::set< int > & getSuccessors()
Returns the Successors vector.
Definition: Vertex.cpp:106
int getIdFrom()
It returns the vertex origin identification.
Definition: Edge.cpp:71
static void getSpatialWeightsFileInfo(std::string pathFileName, std::string &dataSetName, std::string &attrName)
Function used to get information of how a Spatial Weights was generated.
void exportToGAL(te::sa::GeneralizedProximityMatrix *gpm, std::string pathFileName)
Function used to export a gpm to Spatial Weights File GAL Format.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Definition: Exception.h:58
~SpatialWeightsExchanger()
Virtual destructor.
static const std::string sm_factoryGraphTypeDirectedGraph
Directed Graph Factory Name.
Definition: Globals.h:54
Polygon is a subclass of CurvePolygon whose rings are defined by linear rings.
Definition: Polygon.h:50
Point * getCentroid() const
It returns the mathematical centroid for this surface as a point.
int getId()
It returns the vertex id.
Definition: Vertex.cpp:69
A template for atomic data types (integers, floats, strings and others).
Definition: SimpleData.h:59
TEDATAACCESSEXPORT te::gm::GeometryProperty * GetFirstGeomProperty(const DataSetType *dt)
Definition: Utils.cpp:557
static AbstractGraph * make()
It creates and returns an empty graph with default graph type.
virtual AbstractData * clone() const =0
It returns a clone of this object.
virtual te::graph::Vertex * getVertex(int id)=0
It returns the vertex element if it's exist.
void setAttributeName(const std::string &attrName)
std::vector< te::dt::AbstractData * > & getAttributes()
It returns the vector of attributes associated with this element.
Definition: Edge.cpp:81
virtual std::auto_ptr< te::da::DataSetType > getDataSetType(const std::string &name)
It gets information about the given dataset.
Definition: DataSource.cpp:156
void setGraph(te::graph::AbstractGraph *graph)
int getIdTo()
It returns the vertex destiny identification.
Definition: Edge.cpp:76
This class defines the GPM class.
void setParent(Property *p)
It associate this property to the informed parent.
Definition: Property.h:177