-
-
Notifications
You must be signed in to change notification settings - Fork 3k
/
gpsdata.h
348 lines (277 loc) · 10.3 KB
/
gpsdata.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
/***************************************************************************
gpsdata.h - Data structures for GPS data
-------------------
begin : 2004-04-14
copyright : (C) 2004 by Lars Luthman
email : larsl@users.sourceforge.net
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef GPSDATA_H
#define GPSDATA_H
#include <limits>
#include <expat.h>
#include <QString>
#include <QTextStream>
#include <QStack>
#include "qgsrectangle.h"
#include "qgsfeatureid.h"
// workaround for MSVC compiler which already has defined macro max
// that interferes with calling std::numeric_limits<int>::max
#ifdef _MSC_VER
# ifdef max
# undef max
# endif
#endif
/**
* This is the parent class for all GPS data classes (except tracksegment).
It contains the variables that all GPS objects can have.
*/
class QgsGpsObject
{
public:
virtual ~QgsGpsObject() = default;
QString xmlify( const QString &str );
virtual void writeXml( QTextStream &stream );
QString name, cmt, desc, src, url, urlname;
};
/**
* This is the parent class for all GPS point classes. It contains common data
members and common initialization code for all point classes.
*/
class QgsGpsPoint : public QgsGpsObject
{
public:
QgsGpsPoint();
void writeXml( QTextStream &stream ) override;
double lat = 0., lon = 0., ele;
QString sym;
};
/**
* This is the parent class for all GPS object types that can have a nonempty
bounding box (Route, Track). It contains common data members for all
those classes. */
class QgsGpsExtended : public QgsGpsObject
{
public:
QgsGpsExtended();
void writeXml( QTextStream &stream ) override;
double xMin, xMax, yMin, yMax;
int number;
};
// they both have the same data members in GPX, so...
typedef QgsGpsPoint QgsRoutepoint;
typedef QgsGpsPoint QgsTrackpoint;
//! This is the waypoint class. It is a GPSPoint with an ID.
class QgsWaypoint : public QgsGpsPoint
{
public:
void writeXml( QTextStream &stream ) override;
QgsFeatureId id;
};
/**
* This class represents a GPS route.
*/
class QgsRoute : public QgsGpsExtended
{
public:
void writeXml( QTextStream &stream ) override;
QVector<QgsRoutepoint> points;
QgsFeatureId id;
};
/**
* This class represents a GPS track segment, which is a contiguous part of
a track. See the GPX specification for a better explanation.
*/
class QgsTrackSegment
{
public:
QVector<QgsTrackpoint> points;
};
/**
* This class represents a GPS tracklog. It consists of 0 or more track
segments.
*/
class QgsTrack : public QgsGpsExtended
{
public:
void writeXml( QTextStream &stream ) override;
QVector<QgsTrackSegment> segments;
QgsFeatureId id;
};
/**
* This class represents a set of GPS data, for example a GPS layer in QGIS.
*/
class QgsGpsData
{
public:
//! This iterator type is used to iterate over waypoints.
typedef QList<QgsWaypoint>::iterator WaypointIterator;
//! This iterator type is used to iterate over routes.
typedef QList<QgsRoute>::iterator RouteIterator;
//! This iterator type is used to iterate over tracks.
typedef QList<QgsTrack>::iterator TrackIterator;
/**
* This constructor initializes the extent to a nonsense value. Don't try
to use a GPSData object in QGIS without parsing a datafile into it. */
QgsGpsData();
/**
* This function returns a pointer to a dynamically allocated QgsRectangle
which is the bounding box for this dataset. You'll have to deallocate it
yourself. */
QgsRectangle getExtent() const;
//! Sets a default sensible extent. Only applies when there are no actual data.
void setNoDataExtent();
//! Returns the number of waypoints in this dataset.
int getNumberOfWaypoints() const;
//! Returns the number of waypoints in this dataset.
int getNumberOfRoutes() const;
//! Returns the number of waypoints in this dataset.
int getNumberOfTracks() const;
//! This function returns an iterator that points to the first waypoint.
WaypointIterator waypointsBegin();
//! This function returns an iterator that points to the first route.
RouteIterator routesBegin();
//! This function returns an iterator that points to the first track.
TrackIterator tracksBegin();
/**
* This function returns an iterator that points to the end of the
waypoint list. */
WaypointIterator waypointsEnd();
/**
* This function returns an iterator that points to the end of the
route list. */
RouteIterator routesEnd();
/**
* This function returns an iterator that points to the end of the
track list. */
TrackIterator tracksEnd();
/**
* This function tries to add a new waypoint. An iterator to the new
waypoint will be returned (it will be waypointsEnd() if the waypoint
couldn't be added. */
WaypointIterator addWaypoint( double lat, double lon, const QString &name = "",
double ele = -std::numeric_limits<double>::max() );
WaypointIterator addWaypoint( const QgsWaypoint &wpt );
/**
* This function tries to add a new route. It returns an iterator to the
new route. */
RouteIterator addRoute( const QString &name = "" );
RouteIterator addRoute( const QgsRoute &rte );
/**
* This function tries to add a new track. An iterator to the new track
will be returned. */
TrackIterator addTrack( const QString &name = "" );
TrackIterator addTrack( const QgsTrack &trk );
//! This function removes the waypoints whose IDs are in the list.
void removeWaypoints( const QgsFeatureIds &ids );
//! This function removes the routes whose IDs are in the list.
void removeRoutes( const QgsFeatureIds &ids );
//! This function removes the tracks whose IDs are in the list.
void removeTracks( const QgsFeatureIds &ids );
/**
* This function will write the contents of this GPSData object as XML to
the given text stream. */
void writeXml( QTextStream &stream );
/**
* This function returns a pointer to the GPSData object associated with
the file \c file name. If the file does not exist or can't be parsed,
NULL will be returned. If the file is already used by another layer,
a pointer to the same GPSData object will be returned. And if the file
is not used by any other layer, and can be parsed, a new GPSData object
will be created and a pointer to it will be returned. If you use this
function you should also call releaseData() with the same \c file name
when you're done with the GPSData pointer, otherwise the data will stay
in memory forever and you will get an ugly memory leak. */
static QgsGpsData *getData( const QString &fileName );
/**
* Call this function when you're done with a GPSData pointer that you
got earlier using getData(). Do NOT call this function if you haven't
called getData() earlier with the same \c file name, that can cause data
that is still in use to be deleted. */
static void releaseData( const QString &fileName );
//! Operator<< is our friend. For debugging, not for file I/O.
//friend std::ostream& operator<<(std::ostream& os, const GPSData& d);
protected:
QList<QgsWaypoint> waypoints;
QList<QgsRoute> routes;
QList<QgsTrack> tracks;
int nextWaypoint, nextRoute, nextTrack;
double xMin, xMax, yMin, yMax;
//! This is used internally to store GPS data objects (one per file).
typedef QMap<QString, QPair<QgsGpsData *, unsigned> > DataMap;
/**
* This is the static container that maps file names to GPSData objects and
does reference counting, so several providers can use the same GPSData
object. */
static DataMap dataObjects;
};
class QgsGPXHandler
{
public:
explicit QgsGPXHandler( QgsGpsData &data )
: mData( data )
{ }
/**
* This function is called when expat encounters a new start element in
the XML stream. */
bool startElement( const XML_Char *qName, const XML_Char **attr );
/**
* This function is called when expat encounters character data in the
XML stream. */
void characters( const XML_Char *chars, int len );
/**
* This function is called when expat encounters a new end element in
the XML stream. */
bool endElement( const std::string &qName );
// static wrapper functions for the XML handler functions (expat is in C,
// it does not know about member functions)
static void start( void *data, const XML_Char *el, const XML_Char **attr )
{
static_cast<QgsGPXHandler *>( data )->startElement( el, attr );
}
static void end( void *data, const XML_Char *el )
{
static_cast<QgsGPXHandler *>( data )->endElement( el );
}
static void chars( void *data, const XML_Char *chars, int len )
{
static_cast<QgsGPXHandler *>( data )->characters( chars, len );
}
private:
enum ParseMode
{
ParsingDocument,
ParsingWaypoint,
ParsingRoute,
ParsingTrack,
ParsingRoutepoint,
ParsingTrackSegment,
ParsingTrackpoint,
ParsingDouble,
ParsingInt,
ParsingString,
ParsingUnknown
};
//! This is used to keep track of what kind of data we are parsing.
QStack<ParseMode> parseModes;
QgsGpsData &mData;
QgsWaypoint mWpt;
QgsRoute mRte;
QgsTrack mTrk;
QgsRoutepoint mRtept;
QgsTrackSegment mTrkseg;
QgsTrackpoint mTrkpt;
QgsGpsObject *mObj = nullptr;
QString *mString = nullptr;
double *mDouble = nullptr;
int *mInt = nullptr;
QString mCharBuffer;
};
#endif