gpx/types.rs
1//! generic types for GPX
2
3pub use crate::parser::time::Time;
4use geo_types::{Geometry, LineString, MultiLineString, Point, Rect};
5#[cfg(feature = "use-serde")]
6use serde::{Deserialize, Serialize};
7
8/// Allowable GPX versions. Currently, only GPX 1.0 and GPX 1.1 are accepted.
9#[derive(Clone, Copy, Debug, PartialEq)]
10#[cfg_attr(feature = "use-serde", derive(Serialize, Deserialize))]
11#[derive(Default)]
12pub enum GpxVersion {
13 #[default]
14 Unknown,
15 Gpx10,
16 Gpx11,
17}
18
19impl std::fmt::Display for GpxVersion {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 write!(f, "{:?}", self)
22 }
23}
24
25/// Gpx is the root element in the XML file.
26#[derive(Clone, Default, Debug, PartialEq)]
27#[cfg_attr(feature = "use-serde", derive(Serialize, Deserialize))]
28pub struct Gpx {
29 /// Version of the Gpx file.
30 pub version: GpxVersion,
31
32 /// Creator name or URL of the software that created GPX document
33 pub creator: Option<String>,
34
35 /// Metadata about the file.
36 pub metadata: Option<Metadata>,
37
38 /// A list of waypoints.
39 pub waypoints: Vec<Waypoint>,
40
41 /// A list of tracks.
42 pub tracks: Vec<Track>,
43
44 /// A list of routes with a list of point-by-point directions
45 pub routes: Vec<Route>,
46}
47
48/// Information about the copyright holder and any license governing use of this file.
49///
50/// By linking to an appropriate license, you may place your data into the
51/// public domain or grant additional usage rights.
52#[derive(Clone, Default, Debug, PartialEq)]
53#[cfg_attr(feature = "use-serde", derive(Serialize, Deserialize))]
54pub struct GpxCopyright {
55 pub author: Option<String>,
56 pub year: Option<i32>,
57 pub license: Option<String>,
58}
59
60/// Metadata is information about the GPX file, author, and copyright restrictions.
61///
62/// Providing rich, meaningful information about your GPX files allows others to
63/// search for and use your GPS data.
64#[derive(Clone, Default, Debug, PartialEq)]
65#[cfg_attr(feature = "use-serde", derive(Serialize, Deserialize))]
66pub struct Metadata {
67 /// The name of the GPX file.
68 pub name: Option<String>,
69
70 /// A description of the contents of the GPX file.
71 pub description: Option<String>,
72
73 /// The person or organization who created the GPX file.
74 pub author: Option<Person>,
75
76 /// URLs associated with the location described in the file.
77 pub links: Vec<Link>,
78
79 /// The creation date of the file.
80 pub time: Option<Time>,
81
82 /// Keywords associated with the file. Search engines or databases can use
83 /// this information to classify the data.
84 pub keywords: Option<String>,
85
86 /// Information about the copyright holder and any license governing use of this file.
87 pub copyright: Option<GpxCopyright>,
88
89 /// Bounds for the tracks in the GPX.
90 pub bounds: Option<Rect<f64>>,
91 /*extensions: GpxExtensionsType,*/
92}
93
94/// Route represents an ordered list of waypoints representing a series of turn points leading to a destination.
95#[derive(Clone, Default, Debug, PartialEq)]
96#[cfg_attr(feature = "use-serde", derive(Serialize, Deserialize))]
97pub struct Route {
98 /// GPS name of route.
99 pub name: Option<String>,
100
101 /// GPS comment for route.
102 pub comment: Option<String>,
103
104 /// User description of route.
105 pub description: Option<String>,
106
107 /// Source of data. Included to give user some idea of reliability
108 /// and accuracy of data.
109 pub source: Option<String>,
110
111 /// Links to external information about the route.
112 pub links: Vec<Link>,
113
114 /// GPS route number.
115 pub number: Option<u32>,
116
117 /// Type (classification) of route.
118 pub type_: Option<String>,
119
120 /// Each Waypoint holds the coordinates, elevation, timestamp, and metadata
121 /// for a single point in a track.
122 pub points: Vec<Waypoint>,
123}
124
125impl Route {
126 /// Gives the linestring of the segment's points, the sequence of points that
127 /// comprises the track segment.
128 pub fn linestring(&self) -> LineString<f64> {
129 self.points.iter().map(|wpt| wpt.point()).collect()
130 }
131
132 /// Creates a new Route with default values.
133 ///
134 /// ```
135 /// extern crate gpx;
136 /// extern crate geo_types;
137 ///
138 /// use gpx::{Route, Waypoint};
139 /// use geo_types::Point;
140 ///
141 /// fn main() {
142 /// let mut route: Route = Route::new();
143 ///
144 /// let point = Waypoint::new(Point::new(-121.97, 37.24));
145 /// route.points.push(point);
146 /// }
147 ///
148 pub fn new() -> Route {
149 Default::default()
150 }
151}
152
153impl From<Route> for Geometry<f64> {
154 fn from(route: Route) -> Geometry<f64> {
155 Geometry::LineString(route.linestring())
156 }
157}
158
159/// Track represents an ordered list of points describing a path.
160#[derive(Clone, Default, Debug, PartialEq)]
161#[cfg_attr(feature = "use-serde", derive(Serialize, Deserialize))]
162pub struct Track {
163 /// GPS name of track.
164 pub name: Option<String>,
165
166 /// GPS comment for track.
167 pub comment: Option<String>,
168
169 /// User description of track.
170 pub description: Option<String>,
171
172 /// Source of data. Included to give user some idea of reliability
173 /// and accuracy of data.
174 pub source: Option<String>,
175
176 /// Links to external information about the track.
177 pub links: Vec<Link>,
178
179 /// Type (classification) of track.
180 pub type_: Option<String>,
181
182 /// GPS number of track
183 pub number: Option<u32>,
184
185 /// A Track Segment holds a list of Track Points which are logically
186 /// connected in order. To represent a single GPS track where GPS reception
187 /// was lost, or the GPS receiver was turned off, start a new Track Segment
188 /// for each continuous span of track data.
189 pub segments: Vec<TrackSegment>,
190 /* extensions */
191 /* trkSeg */
192}
193
194impl Track {
195 /// Gives the multi-linestring that this track represents, which is multiple
196 /// linestrings.
197 pub fn multilinestring(&self) -> MultiLineString<f64> {
198 self.segments.iter().map(|seg| seg.linestring()).collect()
199 }
200
201 /// Creates a new Track with default values.
202 ///
203 /// ```
204 /// use gpx::{Track, TrackSegment};
205 ///
206 /// let mut track: Track = Track::new();
207 ///
208 /// let segment = TrackSegment::new();
209 /// track.segments.push(segment);
210 pub fn new() -> Track {
211 Default::default()
212 }
213}
214
215impl From<Track> for Geometry<f64> {
216 fn from(track: Track) -> Geometry<f64> {
217 Geometry::MultiLineString(track.multilinestring())
218 }
219}
220
221/// TrackSegment represents a list of track points.
222///
223/// This TrackSegment holds a list of Track Points which are logically
224/// connected in order. To represent a single GPS track where GPS reception
225/// was lost, or the GPS receiver was turned off, start a new Track Segment
226/// for each continuous span of track data.
227#[derive(Clone, Default, Debug, PartialEq)]
228#[cfg_attr(feature = "use-serde", derive(Serialize, Deserialize))]
229pub struct TrackSegment {
230 /// Each Waypoint holds the coordinates, elevation, timestamp, and metadata
231 /// for a single point in a track.
232 pub points: Vec<Waypoint>,
233 /* extensions */
234}
235
236impl TrackSegment {
237 /// Gives the linestring of the segment's points, the sequence of points that
238 /// comprises the track segment.
239 pub fn linestring(&self) -> LineString<f64> {
240 self.points.iter().map(|wpt| wpt.point()).collect()
241 }
242
243 /// Creates a new TrackSegment with default values.
244 ///
245 /// ```
246 /// extern crate gpx;
247 /// extern crate geo_types;
248 ///
249 /// use gpx::{TrackSegment, Waypoint};
250 /// use geo_types::Point;
251 ///
252 /// fn main() {
253 /// let mut trkseg: TrackSegment = TrackSegment::new();
254 ///
255 /// let point = Waypoint::new(Point::new(-121.97, 37.24));
256 /// trkseg.points.push(point);
257 /// }
258 pub fn new() -> TrackSegment {
259 Default::default()
260 }
261}
262
263impl From<TrackSegment> for Geometry<f64> {
264 fn from(track_segment: TrackSegment) -> Geometry<f64> {
265 Geometry::LineString(track_segment.linestring())
266 }
267}
268
269// A Version of geo_types::Point that has the Default trait implemented, which
270// allows us to initialise the GpxPoint with default values compactly
271// in the Waypoint::new function below
272#[derive(Clone, Debug, PartialEq)]
273#[cfg_attr(feature = "use-serde", derive(Serialize, Deserialize))]
274struct GpxPoint(Point<f64>);
275
276impl Default for GpxPoint {
277 fn default() -> GpxPoint {
278 GpxPoint(Point::new(0 as f64, 0 as f64))
279 }
280}
281
282/// Waypoint represents a waypoint, point of interest, or named feature on a
283/// map.
284#[derive(Clone, Default, Debug, PartialEq)]
285#[cfg_attr(feature = "use-serde", derive(Serialize, Deserialize))]
286pub struct Waypoint {
287 /// The geographical point.
288 point: GpxPoint,
289
290 /// Elevation (in meters) of the point.
291 pub elevation: Option<f64>,
292
293 /// Speed (in meters per second) (only in GPX 1.0)
294 pub speed: Option<f64>,
295
296 /// Creation/modification timestamp for element. Date and time in are in
297 /// Univeral Coordinated Time (UTC), not local time! Conforms to ISO 8601
298 /// specification for date/time representation. Fractional seconds are
299 /// allowed for millisecond timing in tracklogs.
300 pub time: Option<Time>,
301
302 /// The GPS name of the waypoint. This field will be transferred to and
303 /// from the GPS. GPX does not place restrictions on the length of this
304 /// field or the characters contained in it. It is up to the receiving
305 /// application to validate the field before sending it to the GPS.
306 pub name: Option<String>,
307
308 /// GPS waypoint comment. Sent to GPS as comment.
309 pub comment: Option<String>,
310
311 /// A text description of the element. Holds additional information about
312 /// the element intended for the user, not the GPS.
313 pub description: Option<String>,
314
315 /// Source of data. Included to give user some idea of reliability and
316 /// accuracy of data. "Garmin eTrex", "USGS quad Boston North", e.g.
317 pub source: Option<String>,
318
319 /// Links to additional information about the waypoint.
320 pub links: Vec<Link>,
321
322 /// Text of GPS symbol name. For interchange with other programs, use the
323 /// exact spelling of the symbol as displayed on the GPS. If the GPS
324 /// abbreviates words, spell them out.
325 pub symbol: Option<String>,
326
327 /// Type (classification) of the waypoint.
328 pub type_: Option<String>,
329
330 // <magvar> degreesType </magvar> [0..1] ?
331 /// Height of geoid in meters above WGS 84. This correspond to the sea level.
332 pub geoidheight: Option<f64>,
333
334 /// Type of GPS fix. `none` means GPS had no fix. To signify "the fix info
335 /// is unknown", leave out `fix` entirely. Value comes from the list
336 /// `{'none'|'2d'|'3d'|'dgps'|'pps'}`, where `pps` means that the military
337 /// signal was used.
338 pub fix: Option<Fix>,
339
340 /// Number of satellites used to calculate the GPX fix.
341 pub sat: Option<u64>,
342
343 /// Horizontal dilution of precision.
344 pub hdop: Option<f64>,
345
346 /// Vertical dilution of precision.
347 pub vdop: Option<f64>,
348
349 /// Positional dilution of precision.
350 pub pdop: Option<f64>,
351
352 #[deprecated = "Prior to gpx 0.9.0 version crate used incorrect field to parse and emit DGPS age. Use `dgps_age` instead. See https://github.com/georust/gpx/issues/21"]
353 pub age: Option<f64>,
354
355 /// Number of seconds since last DGPS update, from the <ageofdgpsdata> element.
356 pub dgps_age: Option<f64>,
357
358 /// ID of DGPS station used in differential correction, in the range [0, 1023].
359 pub dgpsid: Option<u16>,
360 // <extensions> extensionsType </extensions> [0..1] ?
361}
362
363impl Waypoint {
364 /// Gives the geographical point of the waypoint.
365 ///
366 /// ```
367 /// extern crate geo_types;
368 /// extern crate gpx;
369 ///
370 /// use gpx::Waypoint;
371 /// use geo_types::Point;
372 ///
373 /// fn main() {
374 /// // Kind of useless, but it shows the point.
375 /// let wpt = Waypoint::new(Point::new(-121.97, 37.24));
376 /// let point = wpt.point();
377 ///
378 /// println!("waypoint latitude: {}, longitude: {}", point.x(), point.y());
379 /// }
380 /// ```
381 pub fn point(&self) -> Point<f64> {
382 self.point.0 //.0 to extract the geo_types::Point from the tuple struct GpxPoint
383 }
384
385 /// Creates a new Waypoint from a given geographical point.
386 ///
387 /// ```
388 /// extern crate geo_types;
389 /// extern crate gpx;
390 ///
391 /// use gpx::Waypoint;
392 /// use geo_types::Point;
393 ///
394 /// fn main() {
395 /// let point = Point::new(-121.97, 37.24);
396 ///
397 /// let mut wpt = Waypoint::new(point);
398 /// wpt.elevation = Some(553.21);
399 /// }
400 /// ```
401 pub fn new(point: Point<f64>) -> Waypoint {
402 Waypoint {
403 point: GpxPoint(point),
404 ..Default::default()
405 }
406 }
407}
408
409impl From<Waypoint> for Geometry<f64> {
410 fn from(waypoint: Waypoint) -> Geometry<f64> {
411 Geometry::Point(waypoint.point())
412 }
413}
414
415/// Person represents a person or organization.
416#[derive(Clone, Default, Debug, PartialEq)]
417#[cfg_attr(feature = "use-serde", derive(Serialize, Deserialize))]
418pub struct Person {
419 /// Name of person or organization.
420 pub name: Option<String>,
421
422 /// Email address.
423 pub email: Option<String>,
424
425 /// Link to Web site or other external information about person.
426 pub link: Option<Link>,
427}
428
429/// Link represents a link to an external resource.
430///
431/// An external resource could be a web page, digital photo,
432/// video clip, etc., with additional information.
433#[derive(Clone, Default, Debug, PartialEq)]
434#[cfg_attr(feature = "use-serde", derive(Serialize, Deserialize))]
435pub struct Link {
436 /// URL of hyperlink.
437 pub href: String,
438
439 /// Text of hyperlink.
440 pub text: Option<String>,
441
442 /// Mime type of content (image/jpeg)
443 pub type_: Option<String>,
444}
445
446/// Type of the GPS fix.
447#[derive(Clone, Debug, PartialEq)]
448#[cfg_attr(feature = "use-serde", derive(Serialize, Deserialize))]
449pub enum Fix {
450 /// The GPS had no fix. To signify "the fix info is unknown", leave out the Fix entirely.
451 None,
452 /// 2D fix gives only longitude and latitude. It needs a minimum of 3 satellites.
453 TwoDimensional,
454 /// 3D fix gives longitude, latitude and altitude. It needs a minimum of 4 satellites.
455 ThreeDimensional,
456 /// Differential Global Positioning System.
457 DGPS,
458 /// Military signal.
459 PPS,
460 /// Other values that are not in the specification.
461 Other(String),
462}