Orfeo Toolbox  4.0
otbOSMDataToVectorDataGenerator.cxx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: ORFEO Toolbox
4  Language: C++
5  Date: $Date$
6  Version: $Revision$
7 
8 
9  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
10  See OTBCopyright.txt for details.
11 
12 
13  This software is distributed WITHOUT ANY WARRANTY; without even
14  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  PURPOSE. See the above copyright notices for more information.
16 
17 =========================================================================*/
18 
21 #include "itksys/SystemTools.hxx"
22 #include "itkDataObject.h"
23 #include "itkMacro.h"
24 
25 #include "otbTinyXML.h"
26 
27 namespace otb
28 {
29 
31  m_South(43.60185),
32  m_East(1.59323),
33  m_West(1.54911),
34  m_UseUrl(true)
35 {
37 
38  // Initialize the url
39  m_Url = "http://www.openstreetmap.org/api/0.6/map?";
40 
42 
43  m_ClassKey = "Class";
44  m_ClassKeyValue = 1;
45 
46 
47  // Add the key to search by default
48  m_KeyList.push_back("highway");
49  m_KeyList.push_back("building");
50  m_KeyList.push_back("landuse");
51  m_KeyList.push_back("waterway");
52  m_KeyList.push_back("cycleway");
53  m_KeyList.push_back("public_transport");
54  m_KeyList.push_back("railway");
55  m_KeyList.push_back("natural");
56 }
57 
59 {
60 }
61 
62 
64 {
65  // Priority to the URL, if not set check if the filename is
66  // used
67  if(m_UseUrl)
68  {
69  // Get the url
70  std::ostringstream urlStream;
71  urlStream<<m_Url;
72 
73  // TODO : Replace by the new method RetrieveFileFromInMemory
74  m_FileName = "temposmresult.xml";
75 
76  // Add the extent to the url
77  urlStream<<"bbox="<<m_West<<","<<m_South<<","<<m_East<<","<<m_North;
78 
79  // First check if the request does not cross the server
80  // limitations :
81  if (m_Curl->IsCurlReturnHttpError( urlStream.str()))
82  {
83  itkExceptionMacro(<<"The OSM Server returned an Error > =400,"
84  <<" it means that one of server limits are crossed : node/way/relation or area requested");
85  }
86 
87  // Use Curl to request the OSM Server
88  // TODO use the RetrieveUrlInMemory
89  m_Curl->RetrieveFile(urlStream.str(), m_FileName);
90  }
91  else
92  {
93  // Check if the filename is not empty
94  if(m_FileName.empty())
95  itkExceptionMacro(<<"The XML output FileName is empty, please set the filename via the method SetFileName");
96 
97  //Check that the right extension is given : expected .xml */
98  if (itksys::SystemTools::GetFilenameLastExtension(m_FileName) != ".xml"
99  && itksys::SystemTools::GetFilenameLastExtension(m_FileName)!= ".osm" )
100  {
101  itkExceptionMacro(<<itksys::SystemTools::GetFilenameLastExtension(m_FileName)
102  <<" is a wrong Extension FileName : Expected .xml or osm");
103  }
104  }
105 
106  // Parse the XML File
107  this->ParseXmlFile();
108 
109  // Remove the osm temp file only if the url request is used
110  if( m_UseUrl)
111  if(std::remove(m_FileName.c_str()) != 0)
112  {
113  itkExceptionMacro(<< "Error while deleting the file" << m_FileName);
114  }
115 }
116 
118 {
119  // Open the xml file
120  TiXmlDocument doc(m_FileName.c_str());
121 
122  if (!doc.LoadFile())
123  {
124  itkExceptionMacro( <<"Cannot open the file "<<m_FileName );
125  }
126 
127  // Parse the xml
128  TiXmlHandle hDoc(&doc);
129  TiXmlHandle root = hDoc.FirstChildElement();
130 
131  if(!root.ToElement())
132  itkExceptionMacro( "Invalid or corrupted XML file : The field way is not found");
133 
134 
136  /* Step 1 : Store the nodes in a std::map */
138 
139  // Iterate through the tree to get all the nodes and store them in
140  // a std::map
141  for( TiXmlElement* node = root.FirstChild("node").ToElement();
142  node != NULL && strcmp(node->Value(),"node")==0;
143  node = node->NextSiblingElement() )
144  {
145  int id = 0;
146  double longitude = 0.;
147  double latitude = 0.;
148 
149  if ( node->QueryIntAttribute("id", &id) == TIXML_SUCCESS
150  && node->QueryDoubleAttribute("lat", &latitude) == TIXML_SUCCESS
151  && node->QueryDoubleAttribute("lon", &longitude) == TIXML_SUCCESS )
152  {
153  // current point
154  VertexType geoPoint;
155  geoPoint[0] = longitude;
156  geoPoint[1] = latitude;
157 
158  // std::pair to add in the map
159  std::pair<int, VertexType> newEntry;
160  newEntry.first = id;
161  newEntry.second = geoPoint;
162  m_GeoPointContainer.insert(newEntry);
163  }
164  }
166  /* Step 2 : Find the Key and the node ids of the key */
168 
169  // Iterate through the tree to get all the fields ways with tag k=key
170  for( TiXmlElement* currentLayer = root.FirstChildElement("way").ToElement();
171  currentLayer != NULL && strcmp(currentLayer->Value(),"way") ==0;
172  currentLayer = currentLayer->NextSiblingElement() )
173  {
174  bool foundKey = false;
175 
176  // Is the element "way" have a child tag
177  if(currentLayer->FirstChildElement("tag"))
178  {
179  ElementPairType elementPair;
180 
181  // Iterate through the node tag to find the "key"
182  for( TiXmlElement* currentTag = currentLayer->FirstChild("tag")->ToElement();
183  currentTag != NULL;
184  currentTag = currentTag->NextSiblingElement() )
185  {
186  std::string result = currentTag->Attribute("k");
187 
188  if(this->IsKeyPresent(result))
189  {
190  // Set the flag to true;
191  foundKey = true;
192 
193  // Get the value of the key
194  std::string resultValue = currentTag->Attribute("v");
195 
196  // Fill the element informations
197  elementPair.first = result;
198  elementPair.second = resultValue;
199 
200  // Add the key, value to map
201  this->AddKeyTypeToMap(result, resultValue);
202 
203  break;
204  }
205  }
206 
207  if(foundKey)
208  {
209  VectorDataElementType vdelement;
210  PointTypeList pointList;
211 
212  // put the current layer pointer to the begining
213  for( TiXmlElement* currentNode = currentLayer->FirstChildElement("nd");
214  currentNode != NULL;
215  currentNode = currentNode->NextSiblingElement() )
216  {
217  int value=0;
218  if(currentNode->QueryIntAttribute("ref", &value) == TIXML_SUCCESS)
219  {
220  // Add the current point to the list
221  pointList.push_back((*m_GeoPointContainer.find(value)).second);
222  }
223  }
224 
225  // Form the VectorDataElement
226  if(pointList.size() > 0)
227  {
228  vdelement.first = elementPair;
229  vdelement.second = pointList;
230  m_VectorDataElementList.push_back(vdelement);
231  }
232  }
233 
234  } // end if tag k exists
235  }
236 }
237 
238 void
239 OSMDataToVectorDataGenerator::AddKeyTypeToMap(const std::string& key, const std::string& value)
240 {
241  // Is this key present in the map
242  KeyMapType::iterator it = m_KeysMap.find(key);
243 
244  if( it != m_KeysMap.end())
245  {
246  // vector containing the types relative to this key
247  StringVectorType &currentTypes = (*it).second;
248 
249  bool found = false;
250 
251  // Add the type if not present
252  for(unsigned int i = 0; i < currentTypes.size(); ++i)
253  {
254  if(currentTypes[i].compare(value) == 0)
255  found = true;
256  }
257  // if the value was not found add it the currentypes vector
258  if(!found)
259  {
260  currentTypes.push_back(value);
261  }
262  }
263  else
264  {
265  std::pair< std::string, StringVectorType > keytype;
266  keytype.first = key;
267  keytype.second.push_back(value);
268  m_KeysMap.insert(keytype);
269  }
270 }
271 
272 void
273 OSMDataToVectorDataGenerator::ProcessVectorData(const std::string& key, const std::string& value)
274 {
275  // the output
277 
278  // Intitialize the vectordata : EPSG 4326 is for WGS84
280  DataNodeType::Pointer root = m_OutputVectorData->GetDataTree()->GetRoot()->Get();
281  DataNodeType::Pointer document = DataNodeType::New();
282  DataNodeType::Pointer folder = DataNodeType::New();
283 
284  document->SetNodeType(otb::DOCUMENT);
285  folder->SetNodeType(otb::FOLDER);
286 
287  document->SetNodeId("DOCUMENT");
288  folder->SetNodeId("FOLDER");
289 
290  m_OutputVectorData->GetDataTree()->Add(document, root);
291  m_OutputVectorData->GetDataTree()->Add(folder, document);
292 
293  // Form the vector data with the values parsed
294  for(unsigned int idx = 0; idx < m_VectorDataElementList.size(); ++idx)
295  {
296  // Instanciate a datanode
297  DataNodeType::Pointer currentDataNode = DataNodeType::New();
298 
299  // Get the current PointTypeList
300  PointTypeList currentPointList = m_VectorDataElementList[idx].second;
301 
302  // Get the current ElementPairList
303  ElementPairType elementPair = m_VectorDataElementList[idx].first;
304 
305  // Add it to the vector data only if the requested key matches to
306  // elementPair key
307  if(elementPair.first.compare(key) == 0)
308  {
309 
310  // value is empty
311  // or if it is not empty it has to match the requestd value
312  if(value.empty() || elementPair.second.compare(value) == 0)
313  {
314 
315  // If the first and the last vertex are the same = polygon else
316  // line
317  if(currentPointList[0].EuclideanDistanceTo(currentPointList[currentPointList.size()-1]) < 1e-10) // polygon
318  {
319  currentDataNode->SetNodeId("FEATURE_POLYGON");
320  currentDataNode->SetNodeType(otb::FEATURE_POLYGON);
321  PolygonType::Pointer polygon = PolygonType::New();
322  for(unsigned int curVertexId = 0; curVertexId< currentPointList.size(); curVertexId++)
323  {
324  polygon->AddVertex(currentPointList[curVertexId]);
325  }
326  currentDataNode->SetPolygonExteriorRing(polygon);
327  }
328  else // line
329  {
330  LineType::Pointer currentLine = LineType::New();
331  for(unsigned int curVertexId = 0; curVertexId< currentPointList.size(); curVertexId++)
332  {
333  currentLine->AddVertex(currentPointList[curVertexId]);
334  }
335  currentDataNode->SetNodeId("FEATURE_LINE");
336  currentDataNode->SetNodeType(otb::FEATURE_LINE);
337  currentDataNode->SetLine(currentLine);
338  }
339 
340  // Add some fields (TODO : mapnik necessary fields for rendering )
341  currentDataNode->SetFieldAsString("Key", elementPair.first);
342  currentDataNode->SetFieldAsString("type", elementPair.second);
343  currentDataNode->SetFieldAsInt(m_ClassKey, m_ClassKeyValue);
344 
345  // Add the to vectordata
346  m_OutputVectorData->GetDataTree()->Add(currentDataNode, folder);
347  }
348  }
349  }
350 }
351 
354 {
355  if(key.empty())
356  itkExceptionMacro(<<"Requested key is empty, please set a valid one");
357 
358  // First thing to do is to add the key set as parameters in the
359  // KeyList
360  if(!this->IsKeyPresent(key))
361  {
362  // TODO leave this functionnality for AddKey ?
363  m_KeyList.push_back(key);
364  this->ParseXmlFile();
365  }
366 
367  // Build the output
368  this->ProcessVectorData(key,"");
369 
370  // Get the output
371  return m_OutputVectorData;
372 }
373 
375 OSMDataToVectorDataGenerator::GetVectorDataByName(const std::string& key, const std::string& value)
376 {
377  if(key.empty())
378  itkExceptionMacro(<<"Requested key is empty, please set a valid one");
379 
380  // Add the key set as parameters in the KeyList
381  // TODO leave this functionnality for AddKey ?
382  if(!this->IsKeyPresent(key))
383  {
384  m_KeyList.push_back(key);
385  this->ParseXmlFile();
386  }
387 
388  // Build the output
389  this->ProcessVectorData(key, value);
390 
391  // Get the output
392  return m_OutputVectorData;
393 }
394 
395 
396 bool
398 {
399  for(unsigned int i = 0; i < m_KeyList.size(); ++i)
400  if(m_KeyList[i].compare(key) == 0)
401  return true;
402 
403  // Otherwise return false;
404  return false;
405 }
406 
407 
408 }

Generated at Sat Mar 8 2014 16:12:15 for Orfeo Toolbox with doxygen 1.8.3.1