blob: 52c9e1810e49657f80b58bbeb6b45365d37b3553 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
#include "platform/location_service.hpp"
#include "std/target_os.hpp"
#include "std/vector.hpp"
#include "std/ctime.hpp"
namespace
{
static double ApproxDistanceSquareInMeters(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 > 300.0)
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
&& ApproxDistanceSquareInMeters(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<LocationService *> m_services;
PositionFilter m_filter;
bool m_reportFirstEvent;
virtual void OnLocationError(location::TLocationError errorCode)
{
m_observer.OnLocationError(errorCode);
}
virtual void OnLocationUpdated(GpsInfo const & info)
{
if (m_filter.Passes(info))
m_observer.OnLocationUpdated(info);
}
public:
explicit DesktopLocationService(LocationObserver & observer)
: LocationService(observer), m_reportFirstEvent(true)
{
#if defined(OMIM_OS_MAC)
m_services.push_back(CreateAppleLocationService(*this));
#endif
#if defined(OMIM_OS_WINDOWS)
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;
}
};
} // namespace location
location::LocationService * CreateDesktopLocationService(location::LocationObserver & observer)
{
return new location::DesktopLocationService(observer);
}
|