diff --git a/.gitignore b/.gitignore index 1a9e589..7ae5d1f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /target /Cargo.lock +.idea/* **/*.rs.bk rusty-tags.emacs diff --git a/src/reader.rs b/src/reader.rs index d545ff3..4bdb43e 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -19,7 +19,7 @@ use crate::types::{ Geometry, Icon, IconStyle, Kml, KmlDocument, KmlVersion, LabelStyle, LineString, LineStyle, LinearRing, Link, LinkTypeIcon, ListStyle, Location, MultiGeometry, Orientation, Pair, Placemark, Point, PolyStyle, Polygon, RefreshMode, ResourceMap, Scale, SchemaData, - SimpleArrayData, SimpleData, Style, StyleMap, Units, Vec2, ViewRefreshMode, + SimpleArrayData, SimpleData, Style, StyleMap, Track, Units, Vec2, ViewRefreshMode, }; /// Main struct for reading KML documents @@ -416,6 +416,29 @@ where Ok(MultiGeometry { geometries, attrs }) } + fn read_track(&mut self, attrs: HashMap) -> Result, Error> { + let mut coords: Vec> = Vec::new(); + loop { + let mut e = self.reader.read_event_into(&mut self.buf)?; + match e { + Event::Start(ref e) => { + if e.local_name().as_ref() == b"coord" { + let mut coord = coords_from_str(&self.read_str()?.replace(" ", ","))?; + coords.push(coord.remove(0)); + } + } + Event::End(ref mut e) => { + if e.local_name().as_ref() == b"Track" { + break; + } + } + Event::Comment(_) => {} + _ => {} + } + } + Ok(Track { coords, attrs }) + } + fn read_placemark(&mut self, attrs: HashMap) -> Result, Error> { let mut name: Option = None; let mut description: Option = None; @@ -444,6 +467,9 @@ where geometry = Some(Geometry::MultiGeometry(self.read_multi_geometry(attrs)?)) } + b"Track" => { + geometry = Some(Geometry::LineString(self.read_track(attrs)?.into())); + } _ => { let start = e.to_owned(); let start_attrs = Self::read_attrs(start.attributes()); @@ -1890,4 +1916,39 @@ mod tests { }) ); } + + #[test] + fn test_parse_kml_document_with_track() { + let kml_str = r#" + + Test Placemark + + 139.74128033333332 35.60417266666666 30.099999999999998 + 139.73755016666667 35.59745483333334 36.0 + 139.73755018666667 35.58974548333334 40.0 + + + "#; + let kml: Kml = kml_str.parse().unwrap(); + assert_eq!( + kml, + Kml::Placemark(Placemark { + name: Some("Test Placemark".to_string()), + geometry: Some(Geometry::LineString( + vec![ + Coord::new( + 139.74128033333332, + 35.60417266666666, + Some(30.099999999999998) + ), + Coord::new(139.73755016666667, 35.59745483333334, Some(36.0)), + Coord::new(139.73755018666667, 35.58974548333334, Some(40.0)) + ] + .into() + )), + children: vec![], + ..Default::default() + }) + ); + } } diff --git a/src/types/line_string.rs b/src/types/line_string.rs index 08166ab..3689808 100644 --- a/src/types/line_string.rs +++ b/src/types/line_string.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use crate::types::altitude_mode::AltitudeMode; use crate::types::coord::{Coord, CoordType}; +use crate::types::Track; /// `kml:LineString`, [10.7](http://docs.opengeospatial.org/is/12-007r2/12-007r2.html#488) in the /// KML specification @@ -25,3 +26,15 @@ where } } } + +impl From> for LineString +where + T: CoordType + Default, +{ + fn from(track: Track) -> Self { + LineString { + coords: track.coords, + ..Default::default() + } + } +} diff --git a/src/types/mod.rs b/src/types/mod.rs index dd9470e..67afd74 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -13,6 +13,7 @@ mod orientation; mod point; mod polygon; mod scale; +mod track; mod vec2; pub use line_string::LineString; @@ -23,6 +24,7 @@ pub use orientation::Orientation; pub use point::Point; pub use polygon::Polygon; pub use scale::Scale; +pub use track::Track; pub use vec2::{Units, Vec2}; mod element; diff --git a/src/types/track.rs b/src/types/track.rs new file mode 100644 index 0000000..0d5e787 --- /dev/null +++ b/src/types/track.rs @@ -0,0 +1,24 @@ +use std::collections::HashMap; + +use crate::types::coord::CoordType; +use crate::types::Coord; + +/// `kml:Track`, [10.15](https://docs.ogc.org/is/12-007r2/12-007r2.html#611) in the KML +/// specification +#[derive(Clone, Debug, Default, PartialEq, Eq)] +pub struct Track { + pub coords: Vec>, + pub attrs: HashMap, +} + +impl Track +where + T: CoordType + Default, +{ + pub fn new(coords: Vec>) -> Self { + Track { + coords, + ..Default::default() + } + } +}