diff --git a/kml/kml_tests/serdes_tests.cpp b/kml/kml_tests/serdes_tests.cpp index 13df3b66db..27fb9b59ee 100644 --- a/kml/kml_tests/serdes_tests.cpp +++ b/kml/kml_tests/serdes_tests.cpp @@ -814,6 +814,44 @@ UNIT_TEST(Kml_Ver_2_3) -122.203329 37.374780 141.199997 -122.203207 37.374857 140.199997 + + absolute + 0 + + 9.42666332 52.94270656 95 + 2022-12-25T13:12:01.914Z + 9.42682572 52.94270115 94 + 2022-12-25T13:12:36Z + 9.42699411 52.94269624 94 + 2022-12-25T13:12:38Z + 9.42716915 52.94268793 95 + 2022-12-25T13:12:40Z + 9.42736231 52.94266046 95 + 2022-12-25T13:12:42Z + 9.42757536 52.94266963 96 + 2022-12-25T13:12:44Z + + + + 0 + 3.71 + 5.22 + 6.16 + 7.1 + 7.28 + + + + 1.57 + 1.62 + 1.64 + 1.69 + 1.56 + + + + + )"; @@ -832,6 +870,7 @@ UNIT_TEST(Kml_Ver_2_3) TEST_EQUAL(fData.m_tracksData.size(), 1, ()); auto const & lines = fData.m_tracksData[0].m_geometry.m_lines; - TEST_EQUAL(lines.size(), 1, ()); + TEST_EQUAL(lines.size(), 2, ()); TEST_EQUAL(lines[0].size(), 7, ()); + TEST_EQUAL(lines[1].size(), 6, ()); } diff --git a/kml/serdes.cpp b/kml/serdes.cpp index aa10e366dd..9991fe0745 100644 --- a/kml/serdes.cpp +++ b/kml/serdes.cpp @@ -29,9 +29,11 @@ std::string_view const kExtendedData = "ExtendedData"; std::string const kCompilation = "mwm:compilation"; std::string_view const kCoordinates = "coordinates"; -std::string_view const kTrack = "Track"; -std::string_view const gxTrack = "gx:Track"; -std::string_view const gxCoord = "gx:coord"; + +bool IsTrack(std::string const & s) +{ + return s == "Track" || s == "gx:Track"; +} std::string const kKmlHeader = "\n" @@ -724,28 +726,29 @@ void KmlParser::SetOrigin(std::string const & s) m_org = pt; } -void KmlParser::ParseAndAddPoint(MultiGeometry::LineT & line, std::string_view v, char const * separator) +void KmlParser::ParseAndAddPoints(MultiGeometry::LineT & line, std::string_view s, + char const * blockSeparator, char const * coordSeparator) { - geometry::PointWithAltitude point; - if (ParsePointWithAltitude(v, separator, point)) + strings::Tokenize(s, blockSeparator, [&](std::string_view v) { - // We dont't expect vertical surfaces, so do not compare heights here. - // Will get a lot of duplicating points otherwise after import some user KMLs. - // https://github.com/organicmaps/organicmaps/issues/3895 - if (line.empty() || !AlmostEqualAbs(line.back().GetPoint(), point.GetPoint(), kMwmPointAccuracy)) - line.emplace_back(point); - } + geometry::PointWithAltitude point; + if (ParsePointWithAltitude(v, coordSeparator, point)) + { + // We dont't expect vertical surfaces, so do not compare heights here. + // Will get a lot of duplicating points otherwise after import some user KMLs. + // https://github.com/organicmaps/organicmaps/issues/3895 + if (line.empty() || !AlmostEqualAbs(line.back().GetPoint(), point.GetPoint(), kMwmPointAccuracy)) + line.emplace_back(point); + } + }); } -void KmlParser::ParseLineCoordinates(std::string const & s, char const * blockSeparator, char const * coordSeparator) +void KmlParser::ParseLineString(std::string const & s) { m_geometryType = GEOMETRY_TYPE_LINE; MultiGeometry::LineT line; - strings::Tokenize(s, blockSeparator, [&](std::string_view v) - { - ParseAndAddPoint(line, v, coordSeparator); - }); + ParseAndAddPoints(line, s, " \n\r\t", ","); if (line.size() > 1) m_geometry.m_lines.push_back(std::move(line)); @@ -892,7 +895,7 @@ std::string const & KmlParser::GetTagFromEnd(size_t n) const bool KmlParser::IsProcessTrackTag() const { size_t const n = m_tags.size(); - return n >= 3 && m_tags[n - 1] == kTrack && (m_tags[n - 2] == kPlacemark || m_tags[n - 3] == kPlacemark); + return n >= 3 && IsTrack(m_tags[n - 1]) && (m_tags[n - 2] == kPlacemark || m_tags[n - 3] == kPlacemark); } void KmlParser::Pop(std::string const & tag) @@ -1009,14 +1012,14 @@ void KmlParser::CharData(std::string value) auto const TrackTag = [this, &prevTag, &currTag, &value]() { - if (prevTag != kTrack) + if (!IsTrack(prevTag)) return false; - if (currTag == "coord") + if (currTag == "coord" || currTag == "gx:coord") { auto & lines = m_geometry.m_lines; ASSERT(!lines.empty(), ()); - ParseAndAddPoint(lines.back(), value, " "); + ParseAndAddPoints(lines.back(), value, "\n\r\t", " "); } return true; }; @@ -1200,12 +1203,7 @@ void KmlParser::CharData(std::string value) else if (prevTag == "LineString") { if (currTag == kCoordinates) - ParseLineCoordinates(value, " \n\r\t", ","); - } - else if (prevTag == gxTrack) - { - if (currTag == gxCoord) - ParseLineCoordinates(value, "\n\r\t", " "); + ParseLineString(value); } else if (TrackTag()) { @@ -1285,20 +1283,11 @@ void KmlParser::CharData(std::string value) else if (prevTag == "LineString") { if (currTag == kCoordinates) - ParseLineCoordinates(value, " \n\r\t", ","); + ParseLineString(value); } - else if (prevTag == gxTrack) + else if (TrackTag()) { - if (currTag == gxCoord) - ParseLineCoordinates(value, "\n\r\t", " "); - } - } - else if (ppTag == "gx:MultiTrack") - { - if (prevTag == gxTrack) - { - if (currTag == gxCoord) - ParseLineCoordinates(value, "\n\r\t", " "); + // noop } } else if (pppTag == kPlacemark) @@ -1345,7 +1334,7 @@ void KmlParser::CharData(std::string value) } } } - else if (ppTag == "MultiTrack" && TrackTag()) + else if ((ppTag == "MultiTrack" || ppTag == "gx:MultiTrack") && TrackTag()) { // noop } diff --git a/kml/serdes.hpp b/kml/serdes.hpp index ab8d3385b1..54aa82ced5 100644 --- a/kml/serdes.hpp +++ b/kml/serdes.hpp @@ -91,8 +91,9 @@ private: void ResetPoint(); void SetOrigin(std::string const & s); - static void ParseAndAddPoint(MultiGeometry::LineT & line, std::string_view v, char const * separator); - void ParseLineCoordinates(std::string const & s, char const * blockSeparator, char const * coordSeparator); + static void ParseAndAddPoints(MultiGeometry::LineT & line, std::string_view s, + char const * blockSeparator, char const * coordSeparator); + void ParseLineString(std::string const & s); bool MakeValid(); void ParseColor(std::string const &value);