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

marble

  • sources
  • kde-4.14
  • 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 <GeoDataStyle.h>
51 #include <GeoDataPolyStyle.h>
52 #include <GeoDataSchema.h>
53 #include <GeoDataSimpleField.h>
54 #include <GeoDataPlacemark.h>
55 #include <GeoDataLineString.h>
56 #include <GeoDataLinearRing.h>
57 #include <GeoDataPolygon.h>
58 #include <GeoDataPoint.h>
59 #include <GeoDataGeometry.h>
60 
61 using namespace Marble;
62 
63 qreal epsilon = 1.0;
64 
65 // Polygon header flags, representing the type of polygon
66 enum polygonFlagType { LINESTRING = 0, LINEARRING = 1, OUTERBOUNDARY = 2, INNERBOUNDARY = 3, MULTIGEOMETRY = 4 };
67 
68 qreal latDistance( const GeoDataCoordinates &A, const GeoDataCoordinates &B ) {
69  qreal latA = A.latitude( GeoDataCoordinates::Degree );
70  qreal latB = B.latitude( GeoDataCoordinates::Degree );
71  return latB - latA;
72 }
73 
74 qreal lonDistance( const GeoDataCoordinates &A, const GeoDataCoordinates &B ) {
75  qreal lonA = A.longitude( GeoDataCoordinates::Degree );
76  qreal lonB = B.longitude( GeoDataCoordinates::Degree );
77  return lonB - lonA;
78 }
79 
80 qreal nodeDistance( const GeoDataCoordinates &A, const GeoDataCoordinates &B ) {
81  return qMax( qAbs( latDistance( A, B ) ), qAbs( lonDistance( A, B ) ) );
82 }
83 
84 
85 qint16 printFormat16( qreal X ) {
86  return ( ( qint16 )( X * 120 ) );
87 }
88 
89 qint8 printFormat8( qreal X ) {
90  return ( ( qint8 )( X * 120 ) );
91 }
92 
93 quint32 getParentNodes( QVector<GeoDataCoordinates>::Iterator begin, QVector<GeoDataCoordinates>::Iterator end )
94 {
95  quint32 parentNodes = 0;
96 
97  QVector<GeoDataCoordinates>::Iterator it = begin;
98  QVector<GeoDataCoordinates>::Iterator itAux = begin;
99 
100  for ( ; it != end && itAux != end; ++itAux ) {
101  if ( ( nodeDistance( (*it), (*itAux) ) > epsilon ) || ( itAux == begin ) ) { // absolute nodes
102  it = itAux;
103  ++parentNodes;
104  }
105  }
106 
107  return parentNodes;
108 }
109 
110 void printAllNodes( QVector<GeoDataCoordinates>::Iterator begin, QVector<GeoDataCoordinates>::Iterator end, QDataStream &stream )
111 {
112 
113  qint16 nrChildNodes;
114 
115  QVector<GeoDataCoordinates>::Iterator it = begin;
116  QVector<GeoDataCoordinates>::Iterator itAux = begin;
117 
118  for ( ; it != end && itAux != end; ++itAux ) {
119  if ( ( nodeDistance( (*it), (*itAux) ) > epsilon ) || ( itAux == begin ) ) { // absolute nodes
120  it = itAux;
121  nrChildNodes = 0;
122  QVector<GeoDataCoordinates>::Iterator itAux2 = it + 1;
123  for ( ; itAux2 != end && nodeDistance( (*it), (*itAux2) ) <= epsilon; ++itAux2 )
124  ++nrChildNodes;
125 
126  qint16 lat = printFormat16( it->latitude( GeoDataCoordinates::Degree ) );
127  qint16 lon = printFormat16( it->longitude( GeoDataCoordinates::Degree ) );
128 
129  stream << lat << lon << nrChildNodes;
130  }
131  else { // relative nodes
132  qint8 lat = printFormat8( latDistance( (*it), (*itAux) ) );
133  qint8 lon = printFormat8( lonDistance( (*it), (*itAux) ) );
134  stream << lat << lon;
135  }
136  }
137 }
138 
139 int main(int argc, char** argv)
140 {
141  QApplication app(argc,argv);
142 
143 
144  qDebug( " Syntax: shp2pn2 [-i shp-sourcefile -o pn2-targetfile]" );
145 
146  QString inputFilename;
147  int inputIndex = app.arguments().indexOf( "-i" );
148  if ( inputIndex > 0 && inputIndex + 1 < argc )
149  inputFilename = app.arguments().at( inputIndex + 1 );
150 
151  QString outputFilename = "output.pn2";
152  int outputIndex = app.arguments().indexOf("-o");
153  if ( outputIndex > 0 && outputIndex + 1 < argc )
154  outputFilename = app.arguments().at( outputIndex + 1 );
155 
156 
157  MarbleModel *model = new MarbleModel;
158  ParsingRunnerManager* manager = new ParsingRunnerManager( model->pluginManager() );
159 
160  GeoDataDocument* document = manager->openFile( inputFilename );
161 
162  QFile file( outputFilename );
163  file.open( QIODevice::WriteOnly );
164  QDataStream stream( &file );
165 
166  quint8 fileHeaderVersion;
167  quint32 fileHeaderPolygons;
168  bool isMapColorField;
169 
170  fileHeaderVersion = 1;
171  fileHeaderPolygons = 0; // This variable counts the number of polygons inside the document
172  isMapColorField = false; // Whether the file contains mapcolor field or not.
173 
174  QVector<GeoDataFeature*>::Iterator i = document->begin();
175  QVector<GeoDataFeature*>::Iterator const end = document->end();
176 
177  for (; i != end; ++i) {
178  GeoDataPlacemark* placemark = static_cast<GeoDataPlacemark*>( *i );
179 
180  // Types of placemarks
181  GeoDataPolygon* polygon = dynamic_cast<GeoDataPolygon*>( placemark->geometry() );
182  GeoDataLineString* linestring = dynamic_cast<GeoDataLineString*>( placemark->geometry() );
183  GeoDataMultiGeometry* multigeom = dynamic_cast<GeoDataMultiGeometry*>( placemark->geometry() );
184 
185  if ( polygon ) {
186  fileHeaderPolygons += 1 + polygon->innerBoundaries().size(); // outer boundary + number of inner boundaries of the polygon
187  }
188 
189  if ( linestring ) {
190  ++fileHeaderPolygons;
191  }
192 
193  if ( multigeom ) {
194  QVector<GeoDataGeometry*>::Iterator multi = multigeom->begin();
195  QVector<GeoDataGeometry*>::Iterator multiEnd = multigeom->end();
196  for ( ; multi != multiEnd; ++multi ) {
201  GeoDataLineString *lineString = dynamic_cast<GeoDataLineString*>( *multi );
202  GeoDataPolygon *poly = dynamic_cast<GeoDataPolygon*>( *multi );
203  if ( lineString ) {
204  ++fileHeaderPolygons;
205  }
206  if ( poly ) {
207  fileHeaderPolygons += 1 + poly->innerBoundaries().size();
208  }
209  }
210  }
211  }
212 
213  GeoDataSchema schema = document->schema( QString("default") );
214  if ( schema.simpleField("mapcolor13").name() == QString("mapcolor13") ) {
215  isMapColorField = true;
216  }
217 
218  // Write in the beginnig whether the file contains mapcolor or not.
219  stream << fileHeaderVersion << fileHeaderPolygons << isMapColorField;
220 
221  i = document->begin();
222 
223  quint32 polyCurrentID = 0;
224  quint32 polyParentNodes;
225  quint8 polyFlag;
226 
227  for ( ; i != end; ++i ) {
228  GeoDataPlacemark* placemark = static_cast<GeoDataPlacemark*>( *i );
229 
230  // Types of placemarks
231  GeoDataPolygon* polygon = dynamic_cast<GeoDataPolygon*>( placemark->geometry() );
232  GeoDataLineString* linestring = dynamic_cast<GeoDataLineString*>( placemark->geometry() );
233  GeoDataMultiGeometry* multigeom = dynamic_cast<GeoDataMultiGeometry*>( placemark->geometry() );
234 
235  if ( polygon ) {
236  // Outer boundary
237  ++polyCurrentID;
238  QVector<GeoDataCoordinates>::Iterator jBegin = polygon->outerBoundary().begin();
239  QVector<GeoDataCoordinates>::Iterator jEnd = polygon->outerBoundary().end();
240  polyParentNodes = getParentNodes( jBegin, jEnd );
241  polyFlag = OUTERBOUNDARY;
242 
243  if ( isMapColorField ) {
244  quint8 colorIndex = placemark->style()->polyStyle().colorIndex();
245  stream << polyCurrentID << polyParentNodes << polyFlag << colorIndex;
246  }
247  else {
248  stream << polyCurrentID << polyParentNodes <<polyFlag;
249  }
250 
251  printAllNodes( jBegin, jEnd, stream );
252 
253  // Inner boundaries
254  QVector<GeoDataLinearRing>::Iterator inner = polygon->innerBoundaries().begin();
255  QVector<GeoDataLinearRing>::Iterator innerEnd = polygon->innerBoundaries().end();
256 
257  for ( ; inner != innerEnd; ++inner ) {
258  GeoDataLinearRing linearring = static_cast<GeoDataLinearRing>( *inner );
259 
260  ++polyCurrentID;
261  jBegin = linearring.begin();
262  jEnd = linearring.end();
263  polyParentNodes = getParentNodes( jBegin, jEnd );
264  polyFlag = INNERBOUNDARY;
265 
266  stream << polyCurrentID << polyParentNodes << polyFlag;
267 
268  printAllNodes( jBegin, jEnd, stream );
269 
270  }
271 
272  }
273 
274  if ( linestring ) {
275  ++polyCurrentID;
276  QVector<GeoDataCoordinates>::Iterator jBegin = linestring->begin();
277  QVector<GeoDataCoordinates>::Iterator jEnd = linestring->end();
278  polyParentNodes = getParentNodes( jBegin, jEnd );
279  if ( linestring->isClosed() )
280  polyFlag = LINEARRING;
281  else
282  polyFlag = LINESTRING;
283 
284  stream << polyCurrentID << polyParentNodes << polyFlag;
285 
286  printAllNodes( jBegin, jEnd, stream );
287  }
288 
289  if ( multigeom ) {
290 
291  QVector<GeoDataGeometry*>::Iterator multi = multigeom->begin();
292  QVector<GeoDataGeometry*>::Iterator multiEnd = multigeom->end();
293 
294  for ( ; multi != multiEnd; ++multi ) {
295  GeoDataLineString* currLineString = dynamic_cast<GeoDataLineString*>( *multi );
296  GeoDataPolygon *currPolygon = dynamic_cast<GeoDataPolygon*>( *multi );
297 
298  if ( currLineString ) {
299  ++polyCurrentID;
300  QVector<GeoDataCoordinates>::Iterator jBegin = currLineString->begin();
301  QVector<GeoDataCoordinates>::Iterator jEnd = currLineString->end();
302  polyParentNodes = getParentNodes( jBegin, jEnd );
303  if ( currLineString->isClosed() )
304  polyFlag = LINEARRING;
305  else
306  polyFlag = LINESTRING;
307 
308  stream << polyCurrentID << polyParentNodes << polyFlag;
309 
310  printAllNodes( jBegin, jEnd, stream );
311  }
312 
313  else if ( currPolygon ) {
314  // Outer boundary
315  ++polyCurrentID;
316  QVector<GeoDataCoordinates>::Iterator jBegin = currPolygon->outerBoundary().begin();
317  QVector<GeoDataCoordinates>::Iterator jEnd = currPolygon->outerBoundary().end();
318  polyParentNodes = getParentNodes( jBegin, jEnd );
319  polyFlag = OUTERBOUNDARY;
320 
321  if ( isMapColorField ) {
322  quint8 colorIndex = placemark->style()->polyStyle().colorIndex();
323  stream << polyCurrentID << polyParentNodes << polyFlag << colorIndex;
324  }
325  else {
326  stream << polyCurrentID << polyParentNodes <<polyFlag;
327  }
328 
329  printAllNodes( jBegin, jEnd, stream );
330 
331  // Inner boundaries
332  QVector<GeoDataLinearRing>::Iterator inner = currPolygon->innerBoundaries().begin();
333  QVector<GeoDataLinearRing>::Iterator innerEnd = currPolygon->innerBoundaries().end();
334 
335  for ( ; inner != innerEnd; ++inner ) {
336  GeoDataLinearRing linearring = static_cast<GeoDataLinearRing>( *inner );
337 
338  ++polyCurrentID;
339  jBegin = linearring.begin();
340  jEnd = linearring.end();
341  polyParentNodes = getParentNodes( jBegin, jEnd );
342  polyFlag = INNERBOUNDARY;
343 
344  stream << polyCurrentID << polyParentNodes << polyFlag;
345 
346  printAllNodes( jBegin, jEnd, stream );
347  }
348  }
349  }
350  }
351  }
352 }
GeoDataDocument.h
Marble::GeoDataLineString::begin
QVector< GeoDataCoordinates >::Iterator begin()
Returns an iterator that points to the begin of the LineString.
Definition: GeoDataLineString.cpp:193
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:110
printFormat16
qint16 printFormat16(qreal X)
Definition: shp2pn2.cpp:85
Marble::GeoDataDocument
A container for Features, Styles and in the future Schemas.
Definition: GeoDataDocument.h:65
Marble::INNERBOUNDARY
Definition: Pn2Runner.cpp:50
Marble::GeoDataLinearRing
A LinearRing that allows to store a closed, contiguous set of line segments.
Definition: GeoDataLinearRing.h:68
QVector::begin
iterator begin()
GeoDataPolygon.h
Marble::GeoDataMultiGeometry::end
QVector< GeoDataGeometry * >::Iterator end()
Definition: GeoDataMultiGeometry.cpp:140
Marble::ParsingRunnerManager
Definition: ParsingRunnerManager.h:31
QDataStream
MarbleModel.h
This file contains the headers for MarbleModel.
Marble::OUTERBOUNDARY
Definition: Pn2Runner.cpp:50
Marble::GeoDataStyle::polyStyle
GeoDataPolyStyle & polyStyle()
Return the label style of this style.
Definition: GeoDataStyle.cpp:153
QList::at
const T & at(int i) const
GeoDataSimpleField.h
QApplication
GeoDataStyle.h
Marble::GeoDataLineString::end
QVector< GeoDataCoordinates >::Iterator end()
Returns an iterator that points to the end of the LineString.
Definition: GeoDataLineString.cpp:204
Marble::GeoDataFeature::style
const GeoDataStyle * style() const
Return the style assigned to the placemark, or a default style if none has been set.
Definition: GeoDataFeature.cpp:709
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:634
QFile
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:310
Marble::GeoDataPlacemark::geometry
GeoDataGeometry * geometry()
The geometry of the GeoDataPlacemark is to be rendered to the marble map along with the icon at the c...
Definition: GeoDataPlacemark.cpp:152
Marble::LINESTRING
Definition: Pn2Runner.cpp:50
nodeDistance
qreal nodeDistance(const GeoDataCoordinates &A, const GeoDataCoordinates &B)
Definition: shp2pn2.cpp:80
Marble::LINEARRING
Definition: Pn2Runner.cpp:50
Marble::GeoDataSimpleField::name
QString name() const
Definition: GeoDataSimpleField.cpp:70
GeoDataFeature.h
getParentNodes
quint32 getParentNodes(QVector< GeoDataCoordinates >::Iterator begin, QVector< GeoDataCoordinates >::Iterator end)
Definition: shp2pn2.cpp:93
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
GeoDataSchema.h
QString
GeoDataPlacemark.h
QFile::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
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:123
epsilon
qreal epsilon
Definition: shp2pn2.cpp:63
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:139
GeoDataLinearRing.h
Marble::MULTIGEOMETRY
Definition: Pn2Runner.cpp:50
Marble::MarbleModel
The data model (not based on QAbstractModel) for a MarbleWidget.
Definition: MarbleModel.h:97
printFormat8
qint8 printFormat8(qreal X)
Definition: shp2pn2.cpp:89
Marble::polygonFlagType
polygonFlagType
Definition: Pn2Runner.cpp:50
lonDistance
qreal lonDistance(const GeoDataCoordinates &A, const GeoDataCoordinates &B)
Definition: shp2pn2.cpp:74
Marble::GeoDataPolygon::innerBoundaries
QVector< GeoDataLinearRing > & innerBoundaries()
Returns a set of inner boundaries which are represented as LinearRings.
Definition: GeoDataPolygon.cpp:139
GeoDataPoint.h
QVector
Marble::GeoDataSchema
Definition: GeoDataSchema.h:30
Marble::GeoDataPolyStyle::colorIndex
quint8 colorIndex() const
Return the value of color index.
Definition: GeoDataPolyStyle.cpp:125
Marble::GeoDataMultiGeometry
Definition: GeoDataMultiGeometry.h:33
Marble::GeoDataMultiGeometry::begin
QVector< GeoDataGeometry * >::Iterator begin()
Definition: GeoDataMultiGeometry.cpp:134
MarbleWidget.h
This file contains the headers for MarbleWidget.
Marble::GeoDataSchema::simpleField
GeoDataSimpleField & simpleField(const QString &name) const
Definition: GeoDataSchema.cpp:79
QStringList::indexOf
int indexOf(const QRegExp &rx, int from) const
GeoDataGeometry.h
latDistance
qreal latDistance(const GeoDataCoordinates &A, const GeoDataCoordinates &B)
Definition: shp2pn2.cpp:68
QCoreApplication::arguments
QStringList arguments()
QVector::end
iterator end()
Marble::GeoDataPlacemark
a class representing a point of interest on the map
Definition: GeoDataPlacemark.h:54
GeoDataPolyStyle.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:13:42 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
  • 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