From 946bf7b727cce9dbc8a0c1b0f7f7ddec2d2d16cb Mon Sep 17 00:00:00 2001 From: Alex Zolotarev Date: Fri, 21 Oct 2011 18:39:00 +0300 Subject: [qt][ios] Refactored location manager --- platform/location_service.cpp | 116 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 platform/location_service.cpp (limited to 'platform/location_service.cpp') diff --git a/platform/location_service.cpp b/platform/location_service.cpp new file mode 100644 index 0000000000..9ecd552b7c --- /dev/null +++ b/platform/location_service.cpp @@ -0,0 +1,116 @@ +#include "location_service.hpp" + +#include "../std/target_os.hpp" +#include "../std/vector.hpp" +#include "../std/ctime.hpp" + +namespace +{ + +static double ApproxDistanceSquareInMetres(double lat1, double lon1, double lat2, double lon2) +{ + double const m1 = (lat1 - lat2) / 111111.; + double const m2 = (lon1 - lon2) / 111111.; + return m1 * m1 + m2 * m2; +} + +/// Chooses most accurate data from different position services +class PositionFilter +{ + location::GpsInfo * m_prevLocation; +public: + PositionFilter() : m_prevLocation(NULL) {} + ~PositionFilter() { delete m_prevLocation; } + /// @return true if location should be sent to observers + bool Passes(location::GpsInfo const & newLocation) + { + if (time(NULL) - newLocation.m_timestamp > location::POSITION_TIMEOUT_SECONDS) + return false; + + bool passes = true; + if (m_prevLocation) + { + if (newLocation.m_timestamp < m_prevLocation->m_timestamp) + passes = false; + else if (newLocation.m_source != m_prevLocation->m_source + && newLocation.m_horizontalAccuracy > m_prevLocation->m_horizontalAccuracy + && ApproxDistanceSquareInMetres(newLocation.m_latitude, + newLocation.m_longitude, + m_prevLocation->m_latitude, + m_prevLocation->m_longitude) + > newLocation.m_horizontalAccuracy * newLocation.m_horizontalAccuracy) + passes = false; + } + else + m_prevLocation = new location::GpsInfo(newLocation); + return passes; + } +}; + +} // namespace + +extern "C" location::LocationService * CreateAppleLocationService(location::LocationObserver &); +extern "C" location::LocationService * CreateWiFiLocationService(location::LocationObserver &); + +namespace location +{ + class DesktopLocationService : public LocationService, public LocationObserver + { + vector m_services; + PositionFilter m_filter; + bool m_reportFirstEvent; + + virtual void OnLocationStatusChanged(location::TLocationStatus newStatus) + { + m_observer.OnLocationStatusChanged(newStatus); + } + + virtual void OnGpsUpdated(GpsInfo const & info) + { + if (m_reportFirstEvent) + { + m_observer.OnLocationStatusChanged(location::EFirstEvent); + m_reportFirstEvent = false; + } + if (m_filter.Passes(info)) + m_observer.OnGpsUpdated(info); + } + + public: + DesktopLocationService(LocationObserver & observer) + : LocationService(observer), m_reportFirstEvent(true) + { +#if defined(OMIM_OS_MAC) + m_services.push_back(CreateAppleLocationService(*this)); +#endif + +#if defined(OMIM_OS_DESKTOP) + m_services.push_back(CreateWiFiLocationService(*this)); +#endif + } + + virtual ~DesktopLocationService() + { + for (size_t i = 0; i < m_services.size(); ++i) + delete m_services[i]; + } + + virtual void Start() + { + for (size_t i = 0; i < m_services.size(); ++i) + m_services[i]->Start(); + } + + virtual void Stop() + { + for (size_t i = 0; i < m_services.size(); ++i) + m_services[i]->Stop(); + m_reportFirstEvent = true; + } + }; +} + +location::LocationService * CreateDesktopLocationService(location::LocationObserver & observer) +{ + return new location::DesktopLocationService(observer); +} -- cgit v1.2.3