Skip to content

nmeasim::core::track

namespace nmeasim::core::track · Library API

Tracks and routes read from GPX and KML files for the track-following mode, part of the Qt-free nmeasim::core library.

It holds the Track model, the readers parse_gpx (GPX 1.0 and 1.1) and parse_kml (OGC KML 2.2 with the Google gx extensions), and parse_track and load_track, which pick the reader from the file extension. Every reader concatenates all geometries of a file into one Track and reports failure as std::nullopt plus a one-line reason; none of them throws for malformed input. The accepted elements are listed in docs/reference/track-files.md.

See also

Namespaces

Namespace Description
nmeasim::core::track::xml Helpers on top of pugixml shared by the GPX and KML readers of nmeasim::core::track; private to the core library.

Types

Type Description
TrackPoint One point of a track, with the optional values the file recorded for it.
Track A sequence of points to follow, read from one GPX or KML file.

Summary

Enumerations

Name Description
TrackKind The file format and element a track's points came from, for display and for choosing defaults.

Functions

Name Description
parse_gpx() Parses the text of a GPX 1.0 or 1.1 file into a track.
parse_kml() Parses the text of a KML 2.2 file into a track.
to_string() Returns the display name of a track kind, such as GPX route.
parse_track() Parses track file content with the reader that matches the file name's extension.
load_track() Reads a GPX or KML file from disk and parses it with parse_track.

Enumerations

TrackKind

enum class TrackKind

The file format and element a track's points came from, for display and for choosing defaults.

Enumerator Value Description
GpxTrack GPX <trkpt> points of <trk>/<trkseg> elements. Display name GPX track.
GpxRoute GPX <rtept> points of <rte> elements, used when the file has no track point. Display name GPX route.
KmlTrack KML file with at least one <gx:Track> element that provides points, whether or not it also holds <LineString> elements. Display name KML track.
KmlLineString KML file whose points all come from <LineString> elements. Display name KML line.

Declared in src/core/include/nmeasim/core/track/track.hpp:55

Functions

parse_gpx()

std::optional<Track> parse_gpx(std::string_view xml, std::string* error)

Parses the text of a GPX 1.0 or 1.1 file into a track.

Every <trkpt> of every <trkseg> of every <trk> is concatenated in document order and the result is a TrackKind::GpxTrack. When the file has no track point, the <rtept> of every <rte> are used instead and the result is a TrackKind::GpxRoute. <wpt> elements are ignored. Namespace prefixes are ignored, so gpx:trkpt and trkpt are the same element; both versions are read the same way.

For each point:

  • the lat and lon attributes are required, in [-90, 90] and [-180, 180] degrees;
  • <time> is optional; when present and not empty it must be an ISO 8601 time;
  • <ele> (metres), <course> (degrees true) and <speed> (metres per second, converted to knots) are read as direct children, as in GPX 1.0, or from <extensions> or one of its child elements (for example gpxtpx:TrackPointExtension), as GPX 1.1 writers store them. A value that is not a number is treated as absent, without an error.

The track name is the first non-empty one of <metadata>/<name>, <gpx>/<name> and the <trk>/<name> of the tracks in order (or <rte>/<name> for a route).

The file is rejected, with error set to a one-line reason, when:

  • it is not well-formed XML: Invalid XML at offset N: <pugixml description>, where N is the byte offset of the error;
  • the root element is not <gpx>: Not a GPX document: the root element is not <gpx>;
  • a point has no valid lat or lon: point N: missing or invalid lat/lon attribute;
  • a point is out of range: point N: coordinates LAT, LON are out of range;
  • a <time> cannot be parsed: point N: 'TEXT' is not an ISO 8601 time;
  • it has neither track nor route points: No track points (<trkpt>) or route points (<rtept>) found.

N is the 1-based number of the point in the whole file, counted across segments and tracks (or across routes), not within its segment.

Parameters

Name Type Description
xml std::string_view The complete file content, in any encoding pugixml detects. It is copied and need not outlive the call.
error std::string* Receives the reason on failure; left unchanged on success. May be null.

Returns std::optional<Track>: The track, with at least one point, or std::nullopt when the file is rejected.

See also

  • GPX 1.1, elements trk, trkseg, trkpt, rte and rtept.

Declared in src/core/include/nmeasim/core/track/gpx.hpp:54 · defined in src/core/src/track/gpx.cpp:114

parse_kml()

std::optional<Track> parse_kml(std::string_view xml, std::string* error)

Parses the text of a KML 2.2 file into a track.

The whole document under <kml> is traversed. Every <gx:Track> and every <LineString> is concatenated in document order, wherever it sits (<Document>, <Folder>, <Placemark>, <MultiGeometry>, <gx:MultiTrack>). Points, polygons, styles and <TimeStamp> are ignored. Namespace prefixes are ignored.

  • <gx:Track>: each <gx:coord> holds lon lat [alt] separated by whitespace and takes the time of the <when> at the same index. Surplus <when> elements are ignored; a point without a matching <when> has no time, which makes the track untimed.
  • <LineString>: its <coordinates> hold lon,lat[,alt] tuples separated by whitespace. The points have no time.

The third value, when present, is the elevation in metres; one that is not a number is treated as absent, without an error, and values after the third are ignored. The result is a TrackKind::KmlTrack when at least one <gx:Track> provides points, otherwise a TrackKind::KmlLineString. The track name is set at the first geometry: the <name> of the <Placemark> that holds it, else the first non-empty <name> of a <Document> or <Folder> met so far; while both are empty, the next geometry tries again.

The file is rejected, with error set to a one-line reason, when:

  • it is not well-formed XML: Invalid XML at offset N: <pugixml description>, where N is the byte offset of the error;
  • the root element is not <kml>: Not a KML document: the root element is not <kml>;
  • a <when> cannot be parsed, including an empty one: point N: 'TEXT' is not an ISO 8601 time, where N is the point the <when> belongs to;
  • a coordinate has fewer than two values: point N: expected longitude and latitude;
  • its longitude or latitude is not a number: point N: 'LON,LAT' is not numeric;
  • it is out of range: point N: coordinates LAT, LON are out of range, latitude first;
  • no geometry yields a point: No <gx:Track> or <LineString> geometry found.

N is the 1-based number of the point in the whole file, counted across geometries, as parse_gpx counts its points.

Parameters

Name Type Description
xml std::string_view The complete file content, in any encoding pugixml detects. It is copied and need not outlive the call.
error std::string* Receives the reason on failure; left unchanged on success. May be null.

Returns std::optional<Track>: The track, with at least one point, or std::nullopt when the file is rejected.

See also

  • OGC KML 2.2, elements LineString and coordinates; Google KML extensions, gx:Track.

Declared in src/core/include/nmeasim/core/track/kml.hpp:60 · defined in src/core/src/track/kml.cpp:283

to_string()

const char* to_string(TrackKind kind) noexcept

Returns the display name of a track kind, such as GPX route.

Parameters

Name Type Description
kind TrackKind The kind to name.

Returns const char*: A static string, valid for the lifetime of the program: GPX track, GPX route, KML track or KML line, and track for a value outside the enumeration.

Declared in src/core/include/nmeasim/core/track/track.hpp:74 · defined in src/core/src/track/track.cpp:11

parse_track()

std::optional<Track> parse_track(
    std::string_view file_name,
    std::string_view content,
    std::string* error)

Parses track file content with the reader that matches the file name's extension.

The extension is everything after the last . of the file name, the last component of file_name after any / or backslash, compared case-insensitively: gpx selects parse_gpx and kml selects parse_kml. A dot in a directory name is not an extension. The content is not inspected to guess the format.

Parameters

Name Type Description
file_name std::string_view The file name or path; only the extension of its file name is used.
content std::string_view The complete file content.
error std::string* Receives the reason on failure; left unchanged on success. May be null. When the file name has no ., the reason is The track file 'NAME' has no extension; expected .gpx or .kml with the file name without directory; for any other extension it is Unsupported track file type '.EXT'; expected .gpx or .kml with the extension in lower case; otherwise it is the reader's reason.

Returns std::optional<Track>: The track, or std::nullopt when the extension is not supported or the reader rejects the content.

Declared in src/core/include/nmeasim/core/track/track_file.hpp:33 · defined in src/core/src/track/track_file.cpp:62

load_track()

std::optional<Track> load_track(const std::string& path, std::string* error)

Reads a GPX or KML file from disk and parses it with parse_track.

When the file gives the track no name, the name becomes the last component of path, extension included (for example passage.gpx).

Parameters

Name Type Description
path const std::string& Path of the file, in the encoding std::ifstream expects.
error std::string* Receives the reason on failure; left unchanged on success. May be null. It is Cannot read PATH when the file cannot be opened, and PATH: REASON with the reason from parse_track when its content is rejected.

Returns std::optional<Track>: The track, or std::nullopt on failure.

Declared in src/core/include/nmeasim/core/track/track_file.hpp:46 · defined in src/core/src/track/track_file.cpp:81