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);