mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-24 06:53:46 +00:00
@@ -1097,7 +1097,7 @@ kml::CompilationType BookmarkManager::GetCompilationType(kml::MarkGroupId id) co
|
||||
kml::TrackId BookmarkManager::SaveTrackRecording(std::string trackName)
|
||||
{
|
||||
CHECK_THREAD_CHECKER(m_threadChecker, ());
|
||||
auto & tracker = GpsTracker::Instance();
|
||||
auto const & tracker = GpsTracker::Instance();
|
||||
CHECK(!tracker.IsEmpty(), ("Track recording should be not be empty"));
|
||||
|
||||
kml::MultiGeometry geometry;
|
||||
@@ -1105,12 +1105,11 @@ kml::TrackId BookmarkManager::SaveTrackRecording(std::string trackName)
|
||||
geometry.m_timestamps.emplace_back();
|
||||
auto & line = geometry.m_lines.back();
|
||||
auto & timestamps = geometry.m_timestamps.back();
|
||||
|
||||
auto const trackSize = tracker.Finalize();
|
||||
auto const trackSize = tracker.GetTrackSize();
|
||||
line.reserve(trackSize);
|
||||
timestamps.reserve(trackSize);
|
||||
|
||||
tracker.ForEachTrackPoint([&line, ×tamps](location::GpsInfo const & pt, size_t id)
|
||||
tracker.ForEachTrackPoint([&line, ×tamps](location::GpsInfo const & pt, size_t id) -> bool
|
||||
{
|
||||
line.emplace_back(mercator::FromLatLon(pt.m_latitude, pt.m_longitude), pt.m_altitude);
|
||||
timestamps.emplace_back(pt.m_timestamp);
|
||||
|
||||
@@ -3,7 +3,36 @@
|
||||
#include "base/assert.hpp"
|
||||
#include "base/logging.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
using namespace std::chrono;
|
||||
|
||||
namespace gps_track
|
||||
{
|
||||
|
||||
inline pair<size_t, size_t> UnionRanges(pair<size_t, size_t> const & a, pair<size_t, size_t> const & b)
|
||||
{
|
||||
if (a.first == GpsTrack::kInvalidId)
|
||||
{
|
||||
ASSERT_EQUAL(a.second, GpsTrack::kInvalidId, ());
|
||||
return b;
|
||||
}
|
||||
if (b.first == GpsTrack::kInvalidId)
|
||||
{
|
||||
ASSERT_EQUAL(b.second, GpsTrack::kInvalidId, ());
|
||||
return a;
|
||||
}
|
||||
ASSERT_LESS_OR_EQUAL(a.first, a.second, ());
|
||||
ASSERT_LESS_OR_EQUAL(b.first, b.second, ());
|
||||
return make_pair(min(a.first, b.first), max(a.second, b.second));
|
||||
}
|
||||
|
||||
size_t constexpr kItemBlockSize = 1000;
|
||||
|
||||
} // namespace gps_track
|
||||
|
||||
size_t const GpsTrack::kInvalidId = GpsTrackCollection::kInvalidId;
|
||||
|
||||
GpsTrack::GpsTrack(string const & filePath, unique_ptr<IGpsTrackFilter> && filter)
|
||||
: m_filePath(filePath)
|
||||
@@ -70,6 +99,12 @@ void GpsTrack::Clear()
|
||||
ScheduleTask();
|
||||
}
|
||||
|
||||
size_t GpsTrack::GetSize() const
|
||||
{
|
||||
CHECK(m_collection != nullptr, ());
|
||||
return m_collection->GetSize();
|
||||
}
|
||||
|
||||
bool GpsTrack::IsEmpty() const
|
||||
{
|
||||
if (!m_collection)
|
||||
@@ -91,7 +126,6 @@ void GpsTrack::ScheduleTask()
|
||||
{
|
||||
lock_guard<mutex> lg(m_threadGuard);
|
||||
|
||||
/// @todo Replace with !m_thread.joinable() ?
|
||||
if (m_thread.get_id() == std::thread::id())
|
||||
{
|
||||
m_thread = threads::SimpleThread([this]()
|
||||
@@ -99,16 +133,11 @@ void GpsTrack::ScheduleTask()
|
||||
unique_lock<mutex> ul(m_threadGuard);
|
||||
while (true)
|
||||
{
|
||||
m_cv.wait(ul, [this]() { return m_threadExit || m_threadWakeup; });
|
||||
|
||||
if (m_threadWakeup)
|
||||
{
|
||||
m_threadWakeup = false;
|
||||
ProcessPoints();
|
||||
}
|
||||
|
||||
m_cv.wait(ul, [this]() -> bool { return m_threadExit || m_threadWakeup; });
|
||||
if (m_threadExit)
|
||||
break;
|
||||
m_threadWakeup = false;
|
||||
ProcessPoints();
|
||||
}
|
||||
|
||||
m_storage.reset();
|
||||
@@ -150,7 +179,7 @@ void GpsTrack::InitCollection()
|
||||
// and filtered points are inserted in the runtime collection.
|
||||
|
||||
vector<location::GpsInfo> originPoints;
|
||||
originPoints.reserve(GpsTrackStorage::kItemBlockSize);
|
||||
originPoints.reserve(gps_track::kItemBlockSize);
|
||||
|
||||
m_storage->ForEach([this, &originPoints](location::GpsInfo const & originPoint) -> bool
|
||||
{
|
||||
@@ -210,35 +239,13 @@ void GpsTrack::ProcessPoints()
|
||||
vector<location::GpsInfo> points;
|
||||
m_filter->Process(originPoints, points);
|
||||
|
||||
pair<size_t, size_t> addedIds, evictedIds;
|
||||
pair<size_t, size_t> addedIds;
|
||||
pair<size_t, size_t> evictedIds;
|
||||
UpdateCollection(needClear, points, addedIds, evictedIds);
|
||||
|
||||
NotifyCallback(addedIds, evictedIds);
|
||||
}
|
||||
|
||||
size_t GpsTrack::Finalize()
|
||||
{
|
||||
if (m_thread.joinable())
|
||||
{
|
||||
{
|
||||
lock_guard<mutex> lg(m_threadGuard);
|
||||
m_threadWakeup = true;
|
||||
m_threadExit = true;
|
||||
m_cv.notify_one();
|
||||
}
|
||||
m_thread.join();
|
||||
m_thread = {};
|
||||
}
|
||||
|
||||
vector<location::GpsInfo> points;
|
||||
m_filter->Finalize(points);
|
||||
|
||||
if (!points.empty())
|
||||
m_collection->Add(points);
|
||||
|
||||
return m_collection->GetSize();
|
||||
}
|
||||
|
||||
bool GpsTrack::HasCallback()
|
||||
{
|
||||
lock_guard<mutex> lg(m_callbackGuard);
|
||||
|
||||
@@ -11,12 +11,13 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
class GpsTrack final
|
||||
{
|
||||
public:
|
||||
static size_t constexpr kInvalidId = GpsTrackCollection::kInvalidId;
|
||||
static size_t const kInvalidId; // = numeric_limits<size_t>::max();
|
||||
|
||||
/// @param filePath - path to the file on disk to persist track
|
||||
/// @param filter - filter object used for filtering points, GpsTrackNullFilter is created by default
|
||||
@@ -39,6 +40,7 @@ public:
|
||||
void Clear();
|
||||
|
||||
bool IsEmpty() const;
|
||||
size_t GetSize() const;
|
||||
|
||||
/// Notification callback about a change of the gps track.
|
||||
/// @param toAdd - collection of points and ids to add.
|
||||
@@ -55,13 +57,10 @@ public:
|
||||
/// next time callbacks it receives only modifications. It simplifies getter/callback model.
|
||||
void SetCallback(TGpsTrackDiffCallback callback);
|
||||
|
||||
size_t Finalize();
|
||||
|
||||
/// @pre Finalize should be called before.
|
||||
template <class FnT>
|
||||
void ForEachPoint(FnT && fn)
|
||||
template <typename F>
|
||||
void ForEachPoint(F && f) const
|
||||
{
|
||||
m_collection->ForEach(fn);
|
||||
m_collection->ForEach(std::move(f));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "base/assert.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@@ -25,6 +27,8 @@ private:
|
||||
|
||||
} // namespace
|
||||
|
||||
size_t const GpsTrackCollection::kInvalidId = std::numeric_limits<size_t>::max();
|
||||
|
||||
GpsTrackCollection::GpsTrackCollection() : m_lastId(0), m_elevationInfoDirty(true) {}
|
||||
|
||||
std::pair<size_t, size_t> GpsTrackCollection::Add(std::vector<TItem> const & items)
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
|
||||
#include <deque>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
class GpsTrackCollection final
|
||||
{
|
||||
public:
|
||||
static size_t constexpr kInvalidId = std::numeric_limits<size_t>::max();
|
||||
static size_t const kInvalidId; // = numeric_limits<size_t>::max();
|
||||
|
||||
using TItem = location::GpsInfo;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string_view constexpr kMinHorizontalAccuracyKey = "GpsTrackingMinAccuracy";
|
||||
char const kMinHorizontalAccuracyKey[] = "GpsTrackingMinAccuracy";
|
||||
|
||||
// Minimal horizontal accuracy is required to skip 'bad' points.
|
||||
// Use 250 meters to allow points from a pure GPS + GPS through wifi.
|
||||
@@ -56,7 +56,8 @@ GpsTrackFilter::GpsTrackFilter()
|
||||
settings::TryGet(kMinHorizontalAccuracyKey, m_minAccuracy);
|
||||
}
|
||||
|
||||
void GpsTrackFilter::Process(GpsVectorT const & inPoints, GpsVectorT & outPoints)
|
||||
void GpsTrackFilter::Process(std::vector<location::GpsInfo> const & inPoints,
|
||||
std::vector<location::GpsInfo> & outPoints)
|
||||
{
|
||||
outPoints.reserve(inPoints.size());
|
||||
|
||||
@@ -87,20 +88,6 @@ void GpsTrackFilter::Process(GpsVectorT const & inPoints, GpsVectorT & outPoints
|
||||
}
|
||||
}
|
||||
|
||||
void GpsTrackFilter::Finalize(GpsVectorT & outPoints)
|
||||
{
|
||||
if (m_countLastInfo > 0)
|
||||
{
|
||||
// Force append the last point, if wasn't added before.
|
||||
auto const & info = GetLastInfo();
|
||||
if (m_countAcceptedInfo == 0 || info.m_timestamp > GetLastAcceptedInfo().m_timestamp)
|
||||
{
|
||||
outPoints.push_back(info);
|
||||
AddLastAcceptedInfo(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GpsTrackFilter::IsGoodVector(location::GpsInfo const & info) const
|
||||
{
|
||||
ASSERT_GREATER(m_countLastInfo, 1, ());
|
||||
|
||||
@@ -9,16 +9,14 @@ class IGpsTrackFilter
|
||||
public:
|
||||
virtual ~IGpsTrackFilter() = default;
|
||||
|
||||
using GpsVectorT = std::vector<location::GpsInfo>;
|
||||
virtual void Process(GpsVectorT const & inPoints, GpsVectorT & outPoints) = 0;
|
||||
virtual void Finalize(GpsVectorT & outPoints) {}
|
||||
virtual void Process(std::vector<location::GpsInfo> const & inPoints, std::vector<location::GpsInfo> & outPoints) = 0;
|
||||
};
|
||||
|
||||
class GpsTrackNullFilter : public IGpsTrackFilter
|
||||
{
|
||||
public:
|
||||
// IGpsTrackFilter overrides
|
||||
void Process(GpsVectorT const & inPoints, GpsVectorT & outPoints) override;
|
||||
void Process(std::vector<location::GpsInfo> const & inPoints, std::vector<location::GpsInfo> & outPoints) override;
|
||||
};
|
||||
|
||||
class GpsTrackFilter : public IGpsTrackFilter
|
||||
@@ -30,8 +28,7 @@ public:
|
||||
GpsTrackFilter();
|
||||
|
||||
// IGpsTrackFilter overrides
|
||||
void Process(GpsVectorT const & inPoints, GpsVectorT & outPoints) override;
|
||||
void Finalize(GpsVectorT & outPoints) override;
|
||||
void Process(std::vector<location::GpsInfo> const & inPoints, std::vector<location::GpsInfo> & outPoints) override;
|
||||
|
||||
private:
|
||||
bool IsGoodPoint(location::GpsInfo const & info) const;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#include "map/gps_track_storage.hpp"
|
||||
|
||||
#include "coding/endianness.hpp"
|
||||
#include "coding/internal/file_data.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
#include "base/logging.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring> // for memcpy
|
||||
#include <cstring>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -19,6 +20,9 @@ uint32_t constexpr kCurrentVersion = 1;
|
||||
// Header size in bytes, header consists of uint32_t 'version' only
|
||||
uint32_t constexpr kHeaderSize = sizeof(uint32_t);
|
||||
|
||||
// Number of items for batch processing
|
||||
size_t constexpr kItemBlockSize = 1000;
|
||||
|
||||
// TODO
|
||||
// Now GpsInfo written as plain values, but values can be compressed.
|
||||
|
||||
|
||||
@@ -17,9 +17,6 @@ public:
|
||||
DECLARE_EXCEPTION(WriteException, RootException);
|
||||
DECLARE_EXCEPTION(ReadException, RootException);
|
||||
|
||||
// Number of items for batch processing.
|
||||
static size_t constexpr kItemBlockSize = 1000;
|
||||
|
||||
using TItem = location::GpsInfo;
|
||||
|
||||
/// Opens storage with track data.
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
#include "map/gps_tracker.hpp"
|
||||
#include "map/framework.hpp"
|
||||
|
||||
#include "platform/platform.hpp"
|
||||
#include "platform/settings.hpp"
|
||||
|
||||
#include "base/file_name_utils.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "defines.hpp"
|
||||
|
||||
using namespace std::chrono;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
std::string_view constexpr kEnabledKey = "GpsTrackingEnabled";
|
||||
char const kEnabledKey[] = "GpsTrackingEnabled";
|
||||
|
||||
inline std::string GetFilePath()
|
||||
{
|
||||
@@ -68,6 +72,11 @@ bool GpsTracker::IsEmpty() const
|
||||
return m_track.IsEmpty();
|
||||
}
|
||||
|
||||
size_t GpsTracker::GetTrackSize() const
|
||||
{
|
||||
return m_track.GetSize();
|
||||
}
|
||||
|
||||
TrackStatistics GpsTracker::GetTrackStatistics() const
|
||||
{
|
||||
return m_track.GetTrackStatistics();
|
||||
@@ -94,3 +103,9 @@ void GpsTracker::OnLocationUpdated(location::GpsInfo const & info)
|
||||
return;
|
||||
m_track.AddPoint(info);
|
||||
}
|
||||
|
||||
void GpsTracker::ForEachTrackPoint(GpsTrackCallback const & callback) const
|
||||
{
|
||||
CHECK(callback != nullptr, ("Callback should be provided"));
|
||||
m_track.ForEachPoint(callback);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
class GpsTracker
|
||||
@@ -16,7 +17,7 @@ public:
|
||||
void Clear();
|
||||
|
||||
bool IsEmpty() const;
|
||||
|
||||
size_t GetTrackSize() const;
|
||||
TrackStatistics GetTrackStatistics() const;
|
||||
ElevationInfo const & GetElevationInfo() const;
|
||||
|
||||
@@ -29,14 +30,8 @@ public:
|
||||
|
||||
void OnLocationUpdated(location::GpsInfo const & info);
|
||||
|
||||
size_t Finalize() { return m_track.Finalize(); }
|
||||
|
||||
/// @pre Finalize should be called before.
|
||||
template <class FnT>
|
||||
void ForEachTrackPoint(FnT && fn)
|
||||
{
|
||||
m_track.ForEachPoint(fn);
|
||||
}
|
||||
using GpsTrackCallback = std::function<bool(location::GpsInfo const &, size_t)>;
|
||||
void ForEachTrackPoint(GpsTrackCallback const & callback) const;
|
||||
|
||||
private:
|
||||
GpsTracker();
|
||||
|
||||
Reference in New Issue
Block a user