• 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
  • tools
  • shp2pn2
shp2pn2.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 //
9 // For the Natural Earth Layer providing the Default data set at 0.5 arcminute resolution should be enough.
10 // This fileformat allows for even better packed data than the PNT format. For detailed polygons at arcminute
11 // scale on average it should use only 33% of the amount used by PNT.
12 //
13 // Description of the file format
14 //
15 // In the fileformat initially a file header is provided that provides the file format version and the number
16 // of polygons stored inside the file. A Polygon starts with the Polygon Header which provides the feature id
17 // and the number of so called "absolute nodes" that are about to follow. Absolute nodes always contain
18 // absolute geodetic coordinates. The Polygon Header also provides a flag that allows to specify whether the
19 // polygon is supposed to represent a line string ("0") or a linear ring ("1"). Each absolute node can be followed
20 // by relative nodes: These relative nodes are always nodes that follow in correct order inside the polygon after
21 // "their" absolute node. Each absolute node specifies the number of relative nodes which contain relative
22 // coordinates in reference to their absolute node. So an absolute node provides the absolute reference for
23 // relative nodes across a theoretical area of 2x2 squaredegree-area (which in practice frequently might rather
24 // amount to 1x1 square degrees).
25 //
26 // So much of the compression works by just referencing lat/lon diffs to special "absolute nodes". Hence the
27 // compression will especially work well for polygons with many nodes with a high node density.
28 //
29 // The parser has to convert these relative coordinates to absolute coordinates.
30 //
31 // Copyright 2012 Torsten Rahn <rahn@kde.org>
32 // Copyright 2012 Cezar Mocan <mocancezar@gmail.com>
33 //
34 
35 
36 #include <QDebug>
37 #include <QVector>
38 #include <QFileInfo>
39 #include <QFile>
40 #include <QDataStream>
41 #include <QApplication>
42 #include <QTreeView>
43 
44 #include <MarbleWidget.h>
45 #include <MarbleModel.h>
46 #include <ParsingRunnerManager.h>
47 #include <GeoDataTreeModel.h>
48 #include <GeoDataFeature.h>
49 #include <GeoDataDocument.h>
50 #include <GeoDataPlacemark.h>
51 #include <GeoDataLineString.h>
52 #include <GeoDataLinearRing.h>
53 #include <GeoDataPolygon.h>
54 #include <GeoDataPoint.h>
55 #include <GeoDataGeometry.h>
56 
57 using namespace Marble;
58 
59 qreal epsilon = 1.0;
60 
61 // Polygon header flags, representing the type of polygon
62 enum polygonFlagType { LINESTRING = 0, LINEARRING = 1, OUTERBOUNDARY = 2, INNERBOUNDARY = 3, MULTIGEOMETRY = 4 };
63 
64 qreal latDistance( const GeoDataCoordinates &A, const GeoDataCoordinates &B ) {
65  qreal latA = A.latitude( GeoDataCoordinates::Degree );
66  qreal latB = B.latitude( GeoDataCoordinates::Degree );
67  return latB - latA;
68 }
69 
70 qreal lonDistance( const GeoDataCoordinates &A, const GeoDataCoordinates &B ) {
71  qreal lonA = A.longitude( GeoDataCoordinates::Degree );
72  qreal lonB = B.longitude( GeoDataCoordinates::Degree );
73  return lonB - lonA;
74 }
75 
76 qreal nodeDistance( const GeoDataCoordinates &A, const GeoDataCoordinates &B ) {
77  return qMax( qAbs( latDistance( A, B ) ), qAbs( lonDistance( A, B ) ) );
78 }
79 
80 
81 qint16 printFormat16( qreal X ) {
82  return ( ( qint16 )( X * 120 ) );
83 }
84 
85 qint8 printFormat8( qreal X ) {
86  return ( ( qint8 )( X * 120 ) );
87 }
88 
89 quint32 getParentNodes( QVector<GeoDataCoordinates>::Iterator begin, QVector<GeoDataCoordinates>::Iterator end )
90 {
91  quint32 parentNodes = 0;
92 
93  QVector<GeoDataCoordinates>::Iterator it = begin;
94  QVector<GeoDataCoordinates>::Iterator itAux = begin;
95 
96  for ( ; it != end && itAux != end; ++itAux ) {
97  if ( ( nodeDistance( (*it), (*itAux) ) > epsilon ) || ( itAux == begin ) ) { // absolute nodes
98  it = itAux;
99  ++parentNodes;
100  }
101  }
102 
103  return parentNodes;
104 }
105 
106 void printAllNodes( QVector<GeoDataCoordinates>::Iterator begin, QVector<GeoDataCoordinates>::Iterator end, QDataStream &stream )
107 {
108 
109  qint16 nrChildNodes;
110 
111  QVector<GeoDataCoordinates>::Iterator it = begin;
112  QVector<GeoDataCoordinates>::Iterator itAux = begin;
113 
114  for ( ; it != end && itAux != end; ++itAux ) {
115  if ( ( nodeDistance( (*it), (*itAux) ) > epsilon ) || ( itAux == begin ) ) { // absolute nodes
116  it = itAux;
117  nrChildNodes = 0;
118  QVector<GeoDataCoordinates>::Iterator itAux2 = it + 1;
119  for ( ; itAux2 != end && nodeDistance( (*it), (*itAux2) ) <= epsilon; ++itAux2 )
120  ++nrChildNodes;
121 
122  qint16 lat = printFormat16( it->latitude( GeoDataCoordinates::Degree ) );
123  qint16 lon = printFormat16( it->longitude( GeoDataCoordinates::Degree ) );
124 
125  stream << lat << lon << nrChildNodes;
126  }
127  else { // relative nodes
128  qint8 lat = printFormat8( latDistance( (*it), (*itAux) ) );
129  qint8 lon = printFormat8( lonDistance( (*it), (*itAux) ) );
130  stream << lat << lon;
131  }
132  }
133 }
134 
135 int main(int argc, char** argv)
136 {
137  QApplication app(argc,argv);
138 
139 
140  qDebug( " Syntax: pnt2svg [-i shp-sourcefile -o pn2-targetfile]" );
141 
142  QString inputFilename;
143  int inputIndex = app.arguments().indexOf( "-i" );
144  if ( inputIndex > 0 && inputIndex + 1 < argc )
145  inputFilename = app.arguments().at( inputIndex + 1 );
146 
147  QString outputFilename = "output.pn2";
148  int outputIndex = app.arguments().indexOf("-o");
149  if ( outputIndex > 0 && outputIndex + 1 < argc )
150  outputFilename = app.arguments().at( outputIndex + 1 );
151 
152 
153  MarbleModel *model = new MarbleModel;
154  ParsingRunnerManager* manager = new ParsingRunnerManager( model->pluginManager() );
155 
156  GeoDataDocument* document = manager->openFile( inputFilename );
157 
158  QFile file( outputFilename );
159  file.open( QIODevice::WriteOnly );
160  QDataStream stream( &file );
161 
162  quint8 fileHeaderVersion;
163  quint32 fileHeaderPolygons;
164 
165  fileHeaderVersion = 1;
166  fileHeaderPolygons = 0; // This variable counts the number of polygons inside the document
167 
168  QVector<GeoDataFeature*>::Iterator i = document->begin();
169  QVector<GeoDataFeature*>::Iterator const end = document->end();
170 
171  for (; i != end; ++i) {
172  GeoDataPlacemark* placemark = static_cast<GeoDataPlacemark*>( *i );
173 
174  // Types of placemarks
175  GeoDataPolygon* polygon = dynamic_cast<GeoDataPolygon*>( placemark->geometry() );
176  GeoDataLineString* linestring = dynamic_cast<GeoDataLineString*>( placemark->geometry() );
177  GeoDataMultiGeometry* multigeom = dynamic_cast<GeoDataMultiGeometry*>( placemark->geometry() );
178 
179  if ( polygon ) {
180  fileHeaderPolygons += 1 + polygon->innerBoundaries().size(); // outer boundary + number of inner boundaries of the polygon
181  }
182 
183  if ( linestring ) {
184  ++fileHeaderPolygons;
185  }
186 
187  if ( multigeom ) {
188  fileHeaderPolygons += multigeom->size(); // number of polygons inside the multigeometry
189  }
190  }
191 
192  stream << fileHeaderVersion << fileHeaderPolygons;
193 
194  i = document->begin();
195 
196  quint32 polyCurrentID = 0;
197  quint32 polyParentNodes;
198  quint8 polyFlag;
199 
200  for ( ; i != end; ++i ) {
201  GeoDataPlacemark* placemark = static_cast<GeoDataPlacemark*>( *i );
202 
203  // Types of placemarks
204  GeoDataPolygon* polygon = dynamic_cast<GeoDataPolygon*>( placemark->geometry() );
205  GeoDataLineString* linestring = dynamic_cast<GeoDataLineString*>( placemark->geometry() );
206  GeoDataMultiGeometry* multigeom = dynamic_cast<GeoDataMultiGeometry*>( placemark->geometry() );
207 
208  if ( polygon ) {
209 
210  // Outer boundary
211  ++polyCurrentID;
212  QVector<GeoDataCoordinates>::Iterator jBegin = polygon->outerBoundary().begin();
213  QVector<GeoDataCoordinates>::Iterator jEnd = polygon->outerBoundary().end();
214  polyParentNodes = getParentNodes( jBegin, jEnd );
215  polyFlag = OUTERBOUNDARY;
216 
217  stream << polyCurrentID << polyParentNodes << polyFlag;
218 
219  printAllNodes( jBegin, jEnd, stream );
220 
221  // Inner boundaries
222  QVector<GeoDataLinearRing>::Iterator inner = polygon->innerBoundaries().begin();
223  QVector<GeoDataLinearRing>::Iterator innerEnd = polygon->innerBoundaries().end();
224 
225  for ( ; inner != innerEnd; ++inner ) {
226  GeoDataLinearRing linearring = static_cast<GeoDataLinearRing>( *inner );
227 
228  ++polyCurrentID;
229  jBegin = linearring.begin();
230  jEnd = linearring.end();
231  polyParentNodes = getParentNodes( jBegin, jEnd );
232  polyFlag = INNERBOUNDARY;
233 
234  stream << polyCurrentID << polyParentNodes << polyFlag;
235 
236  printAllNodes( jBegin, jEnd, stream );
237 
238  }
239 
240  }
241 
242  if ( linestring ) {
243  ++polyCurrentID;
244  QVector<GeoDataCoordinates>::Iterator jBegin = linestring->begin();
245  QVector<GeoDataCoordinates>::Iterator jEnd = linestring->end();
246  polyParentNodes = getParentNodes( jBegin, jEnd );
247  if ( linestring->isClosed() )
248  polyFlag = LINEARRING;
249  else
250  polyFlag = LINESTRING;
251 
252  stream << polyCurrentID << polyParentNodes << polyFlag;
253 
254  printAllNodes( jBegin, jEnd, stream );
255  }
256 
257  if ( multigeom ) {
258 
259  QVector<GeoDataGeometry*>::Iterator multi = multigeom->begin();
260  QVector<GeoDataGeometry*>::Iterator multiEnd = multigeom->end();
261 
262  for ( ; multi != multiEnd; ++multi ) {
263  GeoDataLineString* currLineString = dynamic_cast<GeoDataLineString*>( *multi );
264 
265  ++polyCurrentID;
266  QVector<GeoDataCoordinates>::Iterator jBegin = currLineString->begin();
267  QVector<GeoDataCoordinates>::Iterator jEnd = currLineString->end();
268  polyParentNodes = getParentNodes( jBegin, jEnd );
269  if ( currLineString->isClosed() )
270  polyFlag = LINEARRING;
271  else
272  polyFlag = LINESTRING;
273 
274  stream << polyCurrentID << polyParentNodes << polyFlag;
275 
276  printAllNodes( jBegin, jEnd, stream );
277  }
278 
279  }
280  }
281 
282 }
GeoDataDocument.h
Marble::GeoDataLineString::begin
QVector< GeoDataCoordinates >::Iterator begin()
Returns an iterator that points to the begin of the LineString.
Definition: GeoDataLineString.cpp:189
Marble::GeoDataCoordinates
A 3d point representation.
Definition: GeoDataCoordinates.h:52
printAllNodes
void printAllNodes(QVector< GeoDataCoordinates >::Iterator begin, QVector< GeoDataCoordinates >::Iterator end, QDataStream &stream)
Definition: shp2pn2.cpp:106
printFormat16
qint16 printFormat16(qreal X)
Definition: shp2pn2.cpp:81
Marble::GeoDataDocument
A container for Features, Styles and in the future Schemas.
Definition: GeoDataDocument.h:64
Marble::INNERBOUNDARY
Definition: Pn2Runner.cpp:48
Marble::GeoDataLinearRing
A LinearRing that allows to store a closed, contiguous set of line segments.
Definition: GeoDataLinearRing.h:68
GeoDataPolygon.h
Marble::GeoDataMultiGeometry::end
QVector< GeoDataGeometry * >::Iterator end()
Definition: GeoDataMultiGeometry.cpp:135
Marble::ParsingRunnerManager
Definition: ParsingRunnerManager.h:31
MarbleModel.h
This file contains the headers for MarbleModel.
Marble::OUTERBOUNDARY
Definition: Pn2Runner.cpp:48
Marble::GeoDataLineString::end
QVector< GeoDataCoordinates >::Iterator end()
Returns an iterator that points to the end of the LineString.
Definition: GeoDataLineString.cpp:200
Marble::GeoDataCoordinates::latitude
qreal latitude(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
retrieves the latitude of the GeoDataCoordinates object use the unit parameter to switch between Radi...
Definition: GeoDataCoordinates.cpp:751
Marble::MarbleModel::pluginManager
const PluginManager * pluginManager() const
Definition: MarbleModel.cpp:564
Marble::GeoDataPlacemark::geometry
GeoDataGeometry * geometry() const
The geometry of the GeoDataPlacemark is to be rendered to the marble map along with the icon at the c...
Definition: GeoDataPlacemark.cpp:63
Marble::GeoDataMultiGeometry::size
int size() const
Definition: GeoDataMultiGeometry.cpp:64
Marble::GeoDataCoordinates::Degree
Definition: GeoDataCoordinates.h:66
ParsingRunnerManager.h
Marble::GeoDataLineString::isClosed
virtual bool isClosed() const
Returns whether a LineString is a closed polygon.
Definition: GeoDataLineString.cpp:275
Marble::LINESTRING
Definition: Pn2Runner.cpp:48
nodeDistance
qreal nodeDistance(const GeoDataCoordinates &A, const GeoDataCoordinates &B)
Definition: shp2pn2.cpp:76
Marble::LINEARRING
Definition: Pn2Runner.cpp:48
GeoDataFeature.h
getParentNodes
quint32 getParentNodes(QVector< GeoDataCoordinates >::Iterator begin, QVector< GeoDataCoordinates >::Iterator end)
Definition: shp2pn2.cpp:89
Marble::ParsingRunnerManager::openFile
GeoDataDocument * openFile(const QString &fileName, DocumentRole role=UserDocument, int timeout=30000)
Definition: ParsingRunnerManager.cpp:121
Marble::GeoDataPolygon
A polygon that can have "holes".
Definition: GeoDataPolygon.h:81
GeoDataLineString.h
GeoDataPlacemark.h
GeoDataTreeModel.h
Marble::GeoDataLineString
A LineString that allows to store a contiguous set of line segments.
Definition: GeoDataLineString.h:75
Marble::GeoDataPolygon::outerBoundary
GeoDataLinearRing & outerBoundary()
Returns the outer boundary that is represented as a LinearRing.
Definition: GeoDataPolygon.cpp:85
epsilon
qreal epsilon
Definition: shp2pn2.cpp:59
Marble::GeoDataCoordinates::longitude
qreal longitude(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
retrieves the longitude of the GeoDataCoordinates object use the unit parameter to switch between Rad...
Definition: GeoDataCoordinates.cpp:739
main
int main(int argc, char **argv)
Definition: shp2pn2.cpp:135
GeoDataLinearRing.h
Marble::MULTIGEOMETRY
Definition: Pn2Runner.cpp:48
Marble::MarbleModel
The data model (not based on QAbstractModel) for a MarbleWidget.
Definition: MarbleModel.h:96
printFormat8
qint8 printFormat8(qreal X)
Definition: shp2pn2.cpp:85
Marble::polygonFlagType
polygonFlagType
Definition: Pn2Runner.cpp:48
lonDistance
qreal lonDistance(const GeoDataCoordinates &A, const GeoDataCoordinates &B)
Definition: shp2pn2.cpp:70
Marble::GeoDataPolygon::innerBoundaries
QVector< GeoDataLinearRing > & innerBoundaries()
Returns a set of inner boundaries which are represented as LinearRings.
Definition: GeoDataPolygon.cpp:101
GeoDataPoint.h
Marble::GeoDataMultiGeometry
Definition: GeoDataMultiGeometry.h:33
Marble::GeoDataMultiGeometry::begin
QVector< GeoDataGeometry * >::Iterator begin()
Definition: GeoDataMultiGeometry.cpp:129
MarbleWidget.h
This file contains the headers for MarbleWidget.
GeoDataGeometry.h
latDistance
qreal latDistance(const GeoDataCoordinates &A, const GeoDataCoordinates &B)
Definition: shp2pn2.cpp:64
Marble::GeoDataPlacemark
a class representing a point of interest on the map
Definition: GeoDataPlacemark.h:54
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:38:52 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