1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-30 22:51:16 +01:00
GPXSee/src/data/gpxparser.cpp

373 lines
10 KiB
C++
Raw Normal View History

2016-10-23 11:09:20 +02:00
#include "gpxparser.h"
2015-10-05 01:43:48 +02:00
qreal GPXParser::number()
{
bool res;
qreal ret = _reader.readElementText().toDouble(&res);
if (!res)
2016-10-29 12:22:28 +02:00
_reader.raiseError(QString("Invalid %1").arg(
_reader.name().toString()));
2015-10-05 01:43:48 +02:00
return ret;
}
QDateTime GPXParser::time()
2016-08-09 01:16:19 +02:00
{
QDateTime d = QDateTime::fromString(_reader.readElementText(),
Qt::ISODate);
if (!d.isValid())
2016-10-29 12:22:28 +02:00
_reader.raiseError(QString("Invalid %1").arg(
_reader.name().toString()));
return d;
2016-08-09 01:16:19 +02:00
}
2019-10-14 01:16:38 +02:00
Link GPXParser::link()
{
QString URL = _reader.attributes().value("href").toString();
QString text;
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("text"))
text = _reader.readElementText();
else
_reader.skipCurrentElement();
}
return Link(URL, text);
}
Coordinates GPXParser::coordinates()
{
bool res;
qreal lon, lat;
const QXmlStreamAttributes &attr = _reader.attributes();
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
lon = attr.value("lon").toString().toDouble(&res);
#else // QT_VERSION < 5
lon = attr.value("lon").toDouble(&res);
#endif // QT_VERSION < 5
if (!res || (lon < -180.0 || lon > 180.0)) {
2016-10-29 12:22:28 +02:00
_reader.raiseError("Invalid longitude");
return Coordinates();
}
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
lat = attr.value("lat").toString().toDouble(&res);
#else // QT_VERSION < 5
lat = attr.value("lat").toDouble(&res);
#endif // QT_VERSION < 5
if (!res || (lat < -90.0 || lat > 90.0)) {
2016-10-29 12:22:28 +02:00
_reader.raiseError("Invalid latitude");
return Coordinates();
}
return Coordinates(lon, lat);
}
2019-02-11 23:28:08 +01:00
void GPXParser::rpExtension(SegmentData *autoRoute)
{
while (_reader.readNextStartElement()) {
2019-11-08 21:00:59 +01:00
if (_reader.name() == QLatin1String("rpt")) {
if (autoRoute)
autoRoute->append(Trackpoint(coordinates()));
}
2018-05-16 22:01:21 +02:00
_reader.skipCurrentElement();
}
}
2016-10-27 08:09:12 +02:00
void GPXParser::tpExtension(Trackpoint &trackpoint)
{
while (_reader.readNextStartElement()) {
2018-08-27 22:25:55 +02:00
if (_reader.name() == QLatin1String("hr"))
2016-11-06 03:28:08 +01:00
trackpoint.setHeartRate(number());
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("atemp"))
2016-11-06 03:28:08 +01:00
trackpoint.setTemperature(number());
else if (_reader.name() == QLatin1String("cad"))
trackpoint.setCadence(number());
else if (_reader.name() == QLatin1String("speed"))
trackpoint.setSpeed(number());
else
_reader.skipCurrentElement();
}
}
2019-11-08 21:00:59 +01:00
void GPXParser::address(Waypoint &waypoint)
{
Address addr;
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("StreetAddress"))
addr.setStreet(_reader.readElementText());
else if (_reader.name() == QLatin1String("City"))
addr.setCity(_reader.readElementText());
else if (_reader.name() == QLatin1String("PostalCode"))
addr.setPostalCode(_reader.readElementText());
else if (_reader.name() == QLatin1String("State"))
addr.setState(_reader.readElementText());
else if (_reader.name() == QLatin1String("Country"))
addr.setCountry(_reader.readElementText());
else
_reader.skipCurrentElement();
}
waypoint.setAddress(addr);
}
void GPXParser::wpExtension(Waypoint &waypoint)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("Address"))
address(waypoint);
else
_reader.skipCurrentElement();
}
}
void GPXParser::waypointExtensions(Waypoint &waypoint, SegmentData *autoRoute)
{
while (_reader.readNextStartElement()) {
2018-08-27 22:25:55 +02:00
if (_reader.name() == QLatin1String("RoutePointExtension"))
rpExtension(autoRoute);
2019-11-08 21:00:59 +01:00
else if (_reader.name() == QLatin1String("WaypointExtension"))
wpExtension(waypoint);
else
_reader.skipCurrentElement();
}
}
void GPXParser::trkptExtensions(Trackpoint &trackpoint)
{
while (_reader.readNextStartElement()) {
2018-08-27 22:25:55 +02:00
if (_reader.name() == QLatin1String("speed"))
2016-11-06 03:28:08 +01:00
trackpoint.setSpeed(number());
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("hr")
|| _reader.name() == QLatin1String("heartrate"))
2016-11-06 03:28:08 +01:00
trackpoint.setHeartRate(number());
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("temp"))
2016-11-06 03:28:08 +01:00
trackpoint.setTemperature(number());
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("cadence"))
2016-11-06 03:28:08 +01:00
trackpoint.setCadence(number());
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("power"))
2016-11-06 03:28:08 +01:00
trackpoint.setPower(number());
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("TrackPointExtension"))
2016-10-27 08:09:12 +02:00
tpExtension(trackpoint);
else
_reader.skipCurrentElement();
}
}
2016-10-27 08:09:12 +02:00
void GPXParser::trackpointData(Trackpoint &trackpoint)
2015-10-05 01:43:48 +02:00
{
qreal gh = NAN;
2015-10-05 01:43:48 +02:00
while (_reader.readNextStartElement()) {
2018-08-27 22:25:55 +02:00
if (_reader.name() == QLatin1String("ele"))
2016-11-06 03:28:08 +01:00
trackpoint.setElevation(number());
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("time"))
2016-11-06 03:28:08 +01:00
trackpoint.setTimestamp(time());
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("geoidheight"))
gh = number();
2019-05-28 23:26:03 +02:00
// GPX 1.0
else if (_reader.name() == QLatin1String("speed"))
trackpoint.setSpeed(number());
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("extensions"))
trkptExtensions(trackpoint);
2015-10-05 01:43:48 +02:00
else
_reader.skipCurrentElement();
}
2016-10-27 08:09:12 +02:00
if (!std::isnan(gh) && !std::isnan(trackpoint.elevation()))
trackpoint.setElevation(trackpoint.elevation() - gh);
2016-08-09 01:16:19 +02:00
}
2019-02-11 23:28:08 +01:00
void GPXParser::waypointData(Waypoint &waypoint, SegmentData *autoRoute)
2016-10-23 11:09:20 +02:00
{
qreal gh = NAN;
2019-10-20 20:30:10 +02:00
Link link10;
2016-10-23 11:09:20 +02:00
while (_reader.readNextStartElement()) {
2018-08-27 22:25:55 +02:00
if (_reader.name() == QLatin1String("name"))
2016-11-06 03:28:08 +01:00
waypoint.setName(_reader.readElementText());
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("desc"))
2016-11-06 03:28:08 +01:00
waypoint.setDescription(_reader.readElementText());
else if (_reader.name() == QLatin1String("cmt"))
waypoint.setComment(_reader.readElementText());
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("ele"))
2016-11-06 03:28:08 +01:00
waypoint.setElevation(number());
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("geoidheight"))
gh = number();
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("time"))
2016-11-06 03:28:08 +01:00
waypoint.setTimestamp(time());
2019-10-20 20:30:10 +02:00
else if (_reader.name() == QLatin1String("link")) {
Link l(link());
if (!l.URL().isEmpty())
waypoint.addLink(l);
} else if (_reader.name() == QLatin1String("url"))
link10.setURL(_reader.readElementText());
else if (_reader.name() == QLatin1String("urlname"))
link10.setText(_reader.readElementText());
2019-11-08 21:00:59 +01:00
else if (_reader.name() == QLatin1String("extensions"))
waypointExtensions(waypoint, autoRoute);
2016-10-23 11:09:20 +02:00
else
_reader.skipCurrentElement();
}
2019-10-20 20:30:10 +02:00
if (!link10.URL().isEmpty())
waypoint.addLink(link10);
if (!std::isnan(gh) && !std::isnan(waypoint.elevation()))
waypoint.setElevation(waypoint.elevation() - gh);
2016-10-23 11:09:20 +02:00
}
2019-02-11 23:28:08 +01:00
void GPXParser::trackpoints(SegmentData &segment)
2015-10-05 01:43:48 +02:00
{
while (_reader.readNextStartElement()) {
2018-08-27 22:25:55 +02:00
if (_reader.name() == QLatin1String("trkpt")) {
2019-02-11 23:28:08 +01:00
segment.append(Trackpoint(coordinates()));
trackpointData(segment.last());
2015-10-05 01:43:48 +02:00
} else
_reader.skipCurrentElement();
}
}
void GPXParser::routepoints(RouteData &route, QList<TrackData> &tracks)
2016-08-09 01:16:19 +02:00
{
TrackData autoRoute;
2019-02-11 23:28:08 +01:00
autoRoute.append(SegmentData());
SegmentData &autoRouteSegment = autoRoute.last();
2019-10-20 20:30:10 +02:00
Link link10;
2016-08-09 01:16:19 +02:00
while (_reader.readNextStartElement()) {
2018-08-27 22:25:55 +02:00
if (_reader.name() == QLatin1String("rtept")) {
2016-10-27 08:27:25 +02:00
route.append(Waypoint(coordinates()));
2019-02-11 23:28:08 +01:00
waypointData(route.last(), &autoRouteSegment);
2018-08-27 22:25:55 +02:00
} else if (_reader.name() == QLatin1String("name"))
route.setName(_reader.readElementText());
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("desc"))
route.setDescription(_reader.readElementText());
else if (_reader.name() == QLatin1String("cmt"))
route.setComment(_reader.readElementText());
2019-10-20 20:30:10 +02:00
else if (_reader.name() == QLatin1String("link")) {
Link l(link());
if (!l.URL().isEmpty())
route.addLink(l);
} else if (_reader.name() == QLatin1String("url"))
link10.setURL(_reader.readElementText());
else if (_reader.name() == QLatin1String("urlname"))
link10.setText(_reader.readElementText());
else
2016-08-09 01:16:19 +02:00
_reader.skipCurrentElement();
}
2019-10-20 20:30:10 +02:00
if (!link10.URL().isEmpty())
route.addLink(link10);
2019-02-11 23:28:08 +01:00
if (!autoRouteSegment.isEmpty()) {
autoRoute.setName(route.name());
autoRoute.setDescription(route.description());
tracks.append(autoRoute);
}
2016-08-09 01:16:19 +02:00
}
void GPXParser::track(TrackData &track)
2015-10-05 01:43:48 +02:00
{
2019-10-20 20:30:10 +02:00
Link link10;
2015-10-05 01:43:48 +02:00
while (_reader.readNextStartElement()) {
2019-02-11 23:28:08 +01:00
if (_reader.name() == QLatin1String("trkseg")) {
track.append(SegmentData());
trackpoints(track.last());
} else if (_reader.name() == QLatin1String("name"))
track.setName(_reader.readElementText());
2018-08-27 22:25:55 +02:00
else if (_reader.name() == QLatin1String("desc"))
track.setDescription(_reader.readElementText());
else if (_reader.name() == QLatin1String("cmt"))
track.setComment(_reader.readElementText());
2019-10-20 20:30:10 +02:00
else if (_reader.name() == QLatin1String("link")) {
Link l(link());
if (!l.URL().isEmpty())
track.addLink(l);
} else if (_reader.name() == QLatin1String("url"))
link10.setURL(_reader.readElementText());
else if (_reader.name() == QLatin1String("urlname"))
link10.setText(_reader.readElementText());
else
2015-10-05 01:43:48 +02:00
_reader.skipCurrentElement();
}
2019-10-20 20:30:10 +02:00
if (!link10.URL().isEmpty())
track.addLink(link10);
2015-10-05 01:43:48 +02:00
}
2019-02-01 00:26:27 +01:00
void GPXParser::area(Area &area)
{
area.append(Polygon());
area.last().append(QVector<Coordinates>());
QVector<Coordinates> &points = area.last().last();
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("point")) {
Coordinates c(coordinates());
_reader.readElementText();
if (c.isValid())
points.append(c);
else
return;
} else if (_reader.name() == QLatin1String("name"))
area.setName(_reader.readElementText());
else if (_reader.name() == QLatin1String("desc"))
area.setDescription(_reader.readElementText());
else
_reader.skipCurrentElement();
}
}
void GPXParser::gpxExtensions(QList<Area> &areas)
{
while (_reader.readNextStartElement()) {
if (_reader.name() == QLatin1String("area")) {
areas.append(Area());
area(areas.last());
} else
_reader.skipCurrentElement();
}
}
2017-07-27 19:47:46 +02:00
void GPXParser::gpx(QList<TrackData> &tracks, QList<RouteData> &routes,
2019-02-01 00:26:27 +01:00
QList<Area> &areas, QVector<Waypoint> &waypoints)
2015-10-05 01:43:48 +02:00
{
while (_reader.readNextStartElement()) {
2018-08-27 22:25:55 +02:00
if (_reader.name() == QLatin1String("trk")) {
2017-07-27 19:47:46 +02:00
tracks.append(TrackData());
track(tracks.back());
2018-08-27 22:25:55 +02:00
} else if (_reader.name() == QLatin1String("rte")) {
2017-07-27 19:47:46 +02:00
routes.append(RouteData());
routepoints(routes.back(), tracks);
2018-08-27 22:25:55 +02:00
} else if (_reader.name() == QLatin1String("wpt")) {
2017-07-27 19:47:46 +02:00
waypoints.append(Waypoint(coordinates()));
waypointData(waypoints.last());
2019-02-01 00:26:27 +01:00
} else if (_reader.name() == QLatin1String("extensions"))
gpxExtensions(areas);
else
2015-10-05 01:43:48 +02:00
_reader.skipCurrentElement();
}
}
2017-07-27 19:47:46 +02:00
bool GPXParser::parse(QFile *file, QList<TrackData> &tracks,
2019-02-01 00:26:27 +01:00
QList<RouteData> &routes, QList<Area> &areas, QVector<Waypoint> &waypoints)
2015-10-05 01:43:48 +02:00
{
2017-07-27 19:47:46 +02:00
_reader.clear();
_reader.setDevice(file);
_reader.setNamespaceProcessing(false);
2017-07-27 19:47:46 +02:00
2015-10-05 01:43:48 +02:00
if (_reader.readNextStartElement()) {
2018-08-27 22:25:55 +02:00
if (_reader.name() == QLatin1String("gpx"))
2019-02-01 00:26:27 +01:00
gpx(tracks, routes, areas, waypoints);
2015-10-05 01:43:48 +02:00
else
2016-10-29 12:22:28 +02:00
_reader.raiseError("Not a GPX file");
2015-10-05 01:43:48 +02:00
}
return !_reader.error();
}