• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.12
  • kdeedu
  • marble
  • src
  • plugins
  • runner
  • json
JsonParser.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the Marble Virtual Globe.
3 
4  This program is free software licensed under the GNU LGPL. You can
5  find a copy of this license in LICENSE.txt in the top directory of
6  the source code.
7 
8  Copyright 2013 Ander Pijoan <ander.pijoan@deusto.es>
9 */
10 
11 #include "JsonParser.h"
12 #include "GeoDataDocument.h"
13 #include "GeoDataPlacemark.h"
14 #include "GeoDataPolygon.h"
15 
16 #include "MarbleDebug.h"
17 
18 #include <QIODevice>
19 
20 
21 namespace Marble {
22 
23 JsonParser::JsonParser() : m_document( 0 )
24 {
25 }
26 
27 JsonParser::~JsonParser()
28 {
29  delete m_document;
30 }
31 
32 GeoDataDocument *JsonParser::releaseDocument()
33 {
34  GeoDataDocument* document = m_document;
35  m_document = 0;
36  return document;
37 }
38 
39 bool JsonParser::read( QIODevice* device )
40 {
41  // Assert previous document got released.
42  delete m_document;
43  m_document = new GeoDataDocument;
44  Q_ASSERT( m_document );
45 
46  // Read file data
47  QString fileData = QString::fromUtf8( device->readAll() );
48 
49  // Create JSON parsing engine
50  // This engine evaluates and returns data from JSON
51  QScriptEngine m_engine;
52 
53  // Store the data into JSON for better managing
54  m_engine.evaluate( "var fileData = " + fileData );
55 
56  if (m_engine.hasUncaughtException()) {
57  mDebug() << "Error parsing GeoJSON : " << m_engine.uncaughtException().toString();
58  return false;
59  }
60 
61  // Start parsing
62 
63  // In GeoJSON format, geometries are stored in features, so we iterate on features
64  if ( m_engine.evaluate( "fileData.features" ).isArray() ) {
65 
66  // Parse each feature
67  for ( int featureCounter = 0 ; featureCounter < m_engine.evaluate( "fileData.features.length" ).toNumber() ; featureCounter ++) {
68 
69  QString count = QString::number(featureCounter);
70 
71  // Check if the feature contains a geometry
72  if ( !m_engine.evaluate( "fileData.features[" + count + "].geometry" ).isUndefined() ) {
73 
74  // Variables for creating the geometry
75  QList<GeoDataGeometry*> geometryList;
76  QList<GeoDataPlacemark*> placemarkList;
77 
78  // Create the different geometry types
79 
80  if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.type" ).toString().toUpper() == "POLYGON" ) {
81 
82  // Check first that there are coordinates
83  if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates" ).isArray() ) {
84 
85  GeoDataPolygon * geom = new GeoDataPolygon( RespectLatitudeCircle | Tessellate );
86 
87  // Coordinates first array will be the outer boundary, if there are more
88  // positions those will be inner holes
89  int ringsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates.length" ).toNumber();
90  for ( int rings = 0 ; rings < ringsCount ; rings ++ ) {
91 
92  QString ringCount = QString::number(rings);
93  GeoDataLinearRing linearRing;
94 
95  int coordinatePairsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[ " + ringCount + " ].length" ).toNumber();
96  for( int coordinatePairs = 0 ; coordinatePairs < coordinatePairsCount ; coordinatePairs++ ) {
97 
98  QString coors = QString::number(coordinatePairs);
99  qreal longitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + ringCount + "][" + coors + "][0]" ).toNumber();
100  qreal latitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + ringCount + "][" + coors + "][1]" ).toNumber();
101 
102  linearRing.append( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) );
103  }
104 
105  // Outer ring
106  if (rings == 0) {
107  geom->setOuterBoundary( linearRing );
108  }
109  // Inner holes
110  else {
111  geom->appendInnerBoundary( linearRing );
112  }
113  }
114  geometryList.append( geom );
115  }
116 
117  } else if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.type" ).toString().toUpper() == "MULTIPOLYGON" ) {
118 
119  // Check first that there are coordinates
120  if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates" ).isArray() ) {
121 
122  int polygonsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates.length" ).toNumber();
123  for ( int polygons = 0 ; polygons < polygonsCount ; polygons++ ) {
124 
125  QString polygon = QString::number( polygons );
126  GeoDataPolygon * geom = new GeoDataPolygon( RespectLatitudeCircle | Tessellate );
127 
128  // Coordinates first array will be the outer boundary, if there are more
129  // positions those will be inner holes
130  int ringsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + polygon + "].length" ).toNumber();
131  for ( int rings = 0 ; rings < ringsCount ; rings ++ ) {
132 
133  QString ringCount = QString::number(rings);
134  GeoDataLinearRing linearRing;
135 
136  int coordinatePairsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + polygon + "][ " + ringCount + " ].length" ).toNumber();
137  for( int coordinatePairs = 0 ; coordinatePairs < coordinatePairsCount ; coordinatePairs++ ) {
138 
139  QString coors = QString::number(coordinatePairs);
140  qreal longitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + polygon + "][" + ringCount + "][" + coors + "][0]" ).toNumber();
141  qreal latitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + polygon + "][" + ringCount + "][" + coors + "][1]" ).toNumber();
142 
143  linearRing.append( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) );
144  }
145 
146  // Outer ring
147  if (rings == 0) {
148  geom->setOuterBoundary( linearRing );
149  }
150  // Inner holes
151  else {
152  geom->appendInnerBoundary( linearRing );
153  }
154  }
155  geometryList.append( geom );
156  }
157  }
158 
159  } else if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.type" ).toString().toUpper() == "LINESTRING" ) {
160 
161  // Check first that there are coordinates
162  if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates" ).isArray() ) {
163 
164  GeoDataLineString * geom = new GeoDataLineString( RespectLatitudeCircle | Tessellate );
165 
166  int coordinatePairsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates.length" ).toNumber();
167  for( int coordinatePairs = 0 ; coordinatePairs < coordinatePairsCount ; coordinatePairs++ ) {
168 
169  QString coors = QString::number(coordinatePairs);
170 
171  qreal longitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + coors + "][0]" ).toNumber();
172  qreal latitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + coors + "][1]" ).toNumber();
173 
174  geom->append( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) );
175  }
176  geometryList.append( geom );
177  }
178 
179  } else if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.type" ).toString().toUpper() == "MULTILINESTRING" ) {
180 
181  // Check first that there are coordinates
182  if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates" ).isArray() ) {
183 
184  int linestringsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates.length" ).toNumber();
185  for( int linestrings = 0 ; linestrings < linestringsCount ; linestrings++ ) {
186 
187  QString linestring = QString::number( linestrings );
188  GeoDataLineString * geom = new GeoDataLineString( RespectLatitudeCircle | Tessellate );
189 
190  int coordinatePairsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + linestring + "].length" ).toNumber();
191  for( int coordinatePairs = 0 ; coordinatePairs < coordinatePairsCount ; coordinatePairs++ ) {
192 
193  QString coors = QString::number(coordinatePairs);
194 
195  qreal longitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + linestring + "][" + coors + "][0]" ).toNumber();
196  qreal latitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + linestring + "][" + coors + "][1]" ).toNumber();
197 
198  geom->append( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) );
199  }
200  geometryList.append( geom );
201  }
202  }
203 
204  } else if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.type" ).toString().toUpper() == "POINT" ) {
205 
206  // Check first that there are coordinates
207  if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates" ).isArray() ) {
208 
209  GeoDataPoint * geom = new GeoDataPoint();
210 
211  qreal longitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[0]" ).toNumber();
212  qreal latitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[1]" ).toNumber();
213 
214  geom->setCoordinates( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) );
215 
216  geometryList.append( geom );
217  }
218  } else if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.type" ).toString().toUpper() == "MULTIPOINT" ) {
219 
220  // Check first that there are coordinates
221  if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates" ).isArray() ) {
222 
223  int pointsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates.length" ).toNumber();
224  for( int points = 0 ; points < pointsCount ; points++ ) {
225 
226  QString point = QString::number(points);
227 
228  GeoDataPoint * geom = new GeoDataPoint();
229 
230  qreal longitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + point + "][0]" ).toNumber();
231  qreal latitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + point + "][1]" ).toNumber();
232 
233  geom->setCoordinates( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) );
234 
235  geometryList.append( geom );
236  }
237  }
238  }
239 
240 
241  // Parse the features properties
242  if ( !geometryList.isEmpty() != 0 && !m_engine.evaluate( "fileData.features[" + count + "].properties" ).isUndefined() ) {
243 
244  QScriptValue properties = m_engine.evaluate( "fileData.features[" + count + "].properties" );
245  QScriptValueIterator propertyIterator ( properties );
246  GeoDataFeature::GeoDataVisualCategory category = GeoDataFeature::None;
247 
248  // First create a placemark for each geometry, there could be multi geometries
249  // that are translated into more than one geometry/placemark
250  for ( int numberGeometries = 0 ; numberGeometries < geometryList.length() ; numberGeometries++ ) {
251  GeoDataPlacemark * placemark = new GeoDataPlacemark();
252  placemarkList.append( placemark );
253  }
254 
255  while ( propertyIterator.hasNext() ) {
256  propertyIterator.next();
257 
258  // If the property read, is the features name
259  if ( propertyIterator.name() == "name" ) {
260  for ( int pl = 0 ; pl < placemarkList.length() ; pl++) {
261  placemarkList.at( pl )->setName( propertyIterator.value().toString() );
262  }
263  }
264  // Else if the geometry still doesnt have a category, try if this
265  // key-value properties match any OSM visual category
266  else if ( category == GeoDataFeature::None ) {
267  category = GeoDataFeature::OsmVisualCategory( propertyIterator.name().toLower() + '=' + propertyIterator.value().toString().toLower() );
268 
269  if ( category != GeoDataFeature::None ) {
270  // Add the visual category to all the placemarks
271  for ( int pl = 0 ; pl < placemarkList.length() ; pl++) {
272  placemarkList.at( pl )->setVisualCategory( category );
273  }
274  }
275  }
276  }
277  }
278 
279  // Add the geometry to the document
280  if ( geometryList.length() == placemarkList.length() ) {
281 
282  while( placemarkList.length() > 0 ) {
283 
284  GeoDataPlacemark * placemark = placemarkList.last();
285  placemarkList.pop_back();
286 
287  GeoDataGeometry * geom = geometryList.last();
288  geometryList.pop_back();
289 
290  placemark->setGeometry( geom );
291  placemark->setVisible( true );
292  m_document->append( placemark );
293  }
294  }
295 
296  // If geometries or placemarks missing inside the lists, delete them
297  qDeleteAll( geometryList.begin(), geometryList.end() );
298  geometryList.clear();
299  qDeleteAll( placemarkList.begin(), placemarkList.end() );
300  placemarkList.clear();
301  }
302  }
303  }
304  return true;
305 }
306 
307 }
308 
GeoDataDocument.h
Marble::GeoDataPoint
A Geometry object representing a 3d point.
Definition: GeoDataPoint.h:47
Marble::GeoDataFeature::OsmVisualCategory
static GeoDataVisualCategory OsmVisualCategory(const QString &keyValue)
Convenience categorization of placemarks for Osm key=value pairs.
Definition: GeoDataFeature.cpp:785
Marble::GeoDataCoordinates
A 3d point representation.
Definition: GeoDataCoordinates.h:52
Marble::GeoDataDocument
A container for Features, Styles and in the future Schemas.
Definition: GeoDataDocument.h:64
Marble::JsonParser::releaseDocument
GeoDataDocument * releaseDocument()
retrieve the parsed document and reset the parser If parsing was successful, retrieve the resulting d...
Definition: JsonParser.cpp:32
Marble::GeoDataLinearRing
A LinearRing that allows to store a closed, contiguous set of line segments.
Definition: GeoDataLinearRing.h:68
JsonParser.h
GeoDataPolygon.h
Marble::JsonParser::~JsonParser
~JsonParser()
Definition: JsonParser.cpp:27
Marble::GeoDataGeometry
A base class for all geodata features.
Definition: GeoDataGeometry.h:47
MarbleDebug.h
Marble::GeoDataCoordinates::Degree
Definition: GeoDataCoordinates.h:66
Marble::JsonParser::read
bool read(QIODevice *)
parse the json file
Definition: JsonParser.cpp:39
Marble::GeoDataPolygon
A polygon that can have "holes".
Definition: GeoDataPolygon.h:81
GeoDataPlacemark.h
Marble::GeoDataLineString::append
void append(const GeoDataCoordinates &position)
Appends a given geodesic position as a new node to the LineString.
Definition: GeoDataLineString.cpp:221
Marble::GeoDataLineString
A LineString that allows to store a contiguous set of line segments.
Definition: GeoDataLineString.h:75
Marble::GeoDataContainer::append
void append(GeoDataFeature *other)
add an element
Definition: GeoDataContainer.cpp:165
Marble::GeoDataPolygon::appendInnerBoundary
void appendInnerBoundary(const GeoDataLinearRing &boundary)
Appends a given LinearRing as an inner boundary of the Polygon.
Definition: GeoDataPolygon.cpp:111
Marble::GeoDataFeature::setVisible
void setVisible(bool value)
Set a new value for visibility.
Definition: GeoDataFeature.cpp:586
Marble::RespectLatitudeCircle
Definition: MarbleGlobal.h:33
Marble::JsonParser::JsonParser
JsonParser()
Definition: JsonParser.cpp:23
Marble::GeoDataFeature::None
Definition: GeoDataFeature.h:76
Marble::GeoDataFeature::GeoDataVisualCategory
GeoDataVisualCategory
A categorization of a placemark as defined by ...FIXME.
Definition: GeoDataFeature.h:75
Marble::Tessellate
Definition: MarbleGlobal.h:32
Marble::GeoDataPlacemark
a class representing a point of interest on the map
Definition: GeoDataPlacemark.h:54
Marble::mDebug
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:31
Marble::GeoDataPolygon::setOuterBoundary
void setOuterBoundary(const GeoDataLinearRing &boundary)
Sets the given LinearRing as an outer boundary of the Polygon.
Definition: GeoDataPolygon.cpp:95
Marble::GeoDataPoint::setCoordinates
void setCoordinates(const GeoDataCoordinates &coordinates)
Definition: GeoDataPoint.cpp:69
Marble::GeoDataPlacemark::setGeometry
void setGeometry(GeoDataGeometry *entry)
Sets the current Geometry of this Placemark.
Definition: GeoDataPlacemark.cpp:136
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:38:50 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal