[map] review fixes

Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
This commit is contained in:
Kiryl Kaveryn 2025-02-20 13:10:15 +04:00 committed by Viktor Havaka
parent 8905269239
commit 83df1e5004
4 changed files with 77 additions and 40 deletions

View file

@ -33,7 +33,6 @@ size_t const GpsTrackCollection::kInvalidId = std::numeric_limits<size_t>::max()
GpsTrackCollection::GpsTrackCollection()
: m_lastId(0)
, m_statistics(TrackStatistics())
{}
std::pair<size_t, size_t> GpsTrackCollection::Add(std::vector<TItem> const & items)

View file

@ -182,4 +182,39 @@ UNIT_TEST(TrackStatistics_SmallAltitudeDelta)
TEST_EQUAL(ts.m_ascent, 1.0, ());
TEST_EQUAL(ts.m_descent, 0, ());
}
UNIT_TEST(TrackStatistics_MixedMultiGeometryAndGpsPoints)
{
kml::MultiGeometry geometry;
auto const point1 = PointWithAltitude({0.0, 0.0}, 100);
auto const point2 = PointWithAltitude({1.0, 1.0}, 150);
auto const point3 = PointWithAltitude({2.0, 2.0}, 50);
geometry.AddLine({
point1,
point2,
point3
});
geometry.AddTimestamps({
5,
6,
7
});
auto ts = TrackStatistics(geometry);
const std::vector<GpsInfo> points = {
BuildGpsInfo(3.0, 3.0, 60, 8),
BuildGpsInfo(4.0, 4.0, 160, 10),
BuildGpsInfo(4.0, 4.0, 20, 15)
};
for (auto const & point : points)
ts.AddGpsInfoPoint(point);
TEST_EQUAL(ts.m_minElevation, 20, ());
TEST_EQUAL(ts.m_maxElevation, 160, ());
TEST_EQUAL(ts.m_ascent, 160, ()); // 50 + 10 + 100
TEST_EQUAL(ts.m_descent, 240, ()); // 100 + 140
TEST_EQUAL(ts.m_duration, 10, ()); // 10
}
} // namespace track_statistics_tests

View file

@ -4,6 +4,8 @@
#include "base/logging.hpp"
using namespace geometry;
using namespace location;
using namespace kml;
double constexpr kInvalidTimestamp = std::numeric_limits<double>::min();
PointWithAltitude const kInvalidPoint = {m2::PointD::Zero(), kInvalidAltitude};
@ -19,58 +21,63 @@ TrackStatistics::TrackStatistics()
m_previousTimestamp(kInvalidTimestamp)
{}
TrackStatistics::TrackStatistics(kml::MultiGeometry const & geometry)
TrackStatistics::TrackStatistics(MultiGeometry const & geometry)
: TrackStatistics()
{
for (auto const & line : geometry.m_lines)
AddPoints(line, true);
AddPoints(line);
if (geometry.HasTimestamps())
{
for (size_t i = 0; i < geometry.m_timestamps.size(); ++i)
{
ASSERT(geometry.HasTimestampsFor(i), ());
AddTimestamps(geometry.m_timestamps[i], true);
AddTimestamps(geometry.m_timestamps[i]);
}
}
}
void TrackStatistics::AddGpsInfoPoint(location::GpsInfo const & point)
void TrackStatistics::AddGpsInfoPoint(GpsInfo const & point)
{
auto const pointWithAltitude = geometry::PointWithAltitude(mercator::FromLatLon(point.m_latitude, point.m_longitude), point.m_altitude);
AddPoints({pointWithAltitude}, false);
AddTimestamps({point.m_timestamp}, false);
}
void TrackStatistics::AddPoints(kml::MultiGeometry::LineT const & line, bool isNewSegment)
{
if (line.empty())
return;
size_t startIndex = 0;
if (HasNoPoints() || isNewSegment)
auto const altitude = Altitude(point.m_altitude);
if (HasNoPoints())
{
InitializeNewSegment(line[0]);
startIndex = 1;
m_minElevation = altitude;
m_maxElevation = altitude;
m_previousPoint = pointWithAltitude;
m_previousTimestamp = point.m_timestamp;
return;
}
ProcessPoints(line, startIndex);
m_minElevation = std::min(m_minElevation, altitude);
m_maxElevation = std::max(m_maxElevation, altitude);
auto const deltaAltitude = altitude - m_previousPoint.GetAltitude();
if (deltaAltitude > 0)
m_ascent += deltaAltitude;
else
m_descent -= deltaAltitude;
m_length += mercator::DistanceOnEarth(m_previousPoint.GetPoint(), pointWithAltitude.GetPoint());
m_duration += point.m_timestamp - m_previousTimestamp;
m_previousPoint = pointWithAltitude;
m_previousTimestamp = point.m_timestamp;
}
void TrackStatistics::InitializeNewSegment(PointWithAltitude const & firstPoint)
void TrackStatistics::AddPoints(Points const & points)
{
auto const altitude = firstPoint.GetAltitude();
if (points.empty())
return;
bool const hasNoPoints = HasNoPoints();
auto const & firstPoint = points[0];
auto const altitude = firstPoint.GetAltitude();
m_minElevation = hasNoPoints ? altitude : std::min(m_minElevation, altitude);
m_maxElevation = hasNoPoints ? altitude : std::max(m_maxElevation, altitude);
m_previousPoint = firstPoint;
}
void TrackStatistics::ProcessPoints(kml::MultiGeometry::LineT const & points, size_t startIndex)
{
for (size_t i = startIndex; i < points.size(); ++i)
for (size_t i = 1; i < points.size(); ++i)
{
auto const & point = points[i];
auto const pointAltitude = point.GetAltitude();
@ -89,16 +96,11 @@ void TrackStatistics::ProcessPoints(kml::MultiGeometry::LineT const & points, si
}
}
void TrackStatistics::AddTimestamps(kml::MultiGeometry::TimeT const & timestamps, bool isNewSegment)
void TrackStatistics::AddTimestamps(Timestamps const & timestamps)
{
if (timestamps.empty())
return;
if (m_previousTimestamp == kInvalidTimestamp)
m_previousTimestamp = timestamps.front();
auto const baseTimestamp = isNewSegment ? timestamps.front() : m_previousTimestamp;
m_duration += timestamps.back() - baseTimestamp;
m_duration += timestamps.back() - timestamps.front();
m_previousTimestamp = timestamps.back();
}

View file

@ -6,6 +6,9 @@
struct TrackStatistics
{
using Points = kml::MultiGeometry::LineT;
using Timestamps = kml::MultiGeometry::TimeT;
TrackStatistics();
explicit TrackStatistics(kml::MultiGeometry const & geometry);
@ -13,15 +16,13 @@ struct TrackStatistics
double m_duration;
double m_ascent;
double m_descent;
int16_t m_minElevation;
int16_t m_maxElevation;
geometry::Altitude m_minElevation;
geometry::Altitude m_maxElevation;
void AddGpsInfoPoint(location::GpsInfo const & point);
private:
void AddPoints(kml::MultiGeometry::LineT const & line, bool isNewSegment);
void AddTimestamps(kml::MultiGeometry::TimeT const & timestamps, bool isNewSegment);
void InitializeNewSegment(geometry::PointWithAltitude const & firstPoint);
void ProcessPoints(kml::MultiGeometry::LineT const & points, size_t startIndex);
void AddPoints(Points const & points);
void AddTimestamps(Timestamps const & timestamps);
bool HasNoPoints() const;
geometry::PointWithAltitude m_previousPoint;