diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index 73148d9b56..9ba64b7c67 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -1389,12 +1389,10 @@ extern "C" Java_com_mapswithme_maps_Framework_predictLocation(JNIEnv * env, jobject thiz, jdouble lat, jdouble lon, jdouble accuracy, jdouble bearing, jdouble speed, jdouble elapsedSeconds) { - double offsetInM = static_cast(speed * elapsedSeconds); - double angle = my::DegToRad(90.0 - static_cast(bearing)); - m2::PointD mercatorPt = MercatorBounds::MetresToXY(lon, lat, accuracy).Center(); - mercatorPt = MercatorBounds::GetSmPoint(mercatorPt, mercatorPt.x * cos(angle), mercatorPt.y * sin(angle)); - - double latlon[] = {MercatorBounds::YToLat(mercatorPt.y), MercatorBounds::XToLon(mercatorPt.x)}; + double latitude = lat; + double longitude = lon; + ::Framework::PredictLocation(lat, lon, accuracy, bearing, speed, elapsedSeconds); + double latlon[] = { lat, lon }; jdoubleArray jLatLon = env->NewDoubleArray(2); env->SetDoubleArrayRegion(jLatLon, 0, 2, latlon); diff --git a/android/src/com/mapswithme/maps/location/LocationPredictor.java b/android/src/com/mapswithme/maps/location/LocationPredictor.java index e8303fb967..87919da47b 100644 --- a/android/src/com/mapswithme/maps/location/LocationPredictor.java +++ b/android/src/com/mapswithme/maps/location/LocationPredictor.java @@ -2,7 +2,6 @@ package com.mapswithme.maps.location; import android.location.Location; import android.os.Handler; -import android.util.Log; import com.mapswithme.maps.Framework; import com.mapswithme.maps.LocationState; @@ -12,9 +11,18 @@ public class LocationPredictor final private long PREDICTION_INTERVAL = 200; final private long MAX_PREDICTION_COUNT = 20; + private Runnable mRunnable = null; + private Handler mHandler = null; + + private LocationService.LocationListener mListener = null; + private Location mLastLocation = null; + private boolean mGeneratePredictions = false; + private int mPredictionCount = 0; + private int mConnectionSlot = 0; + public LocationPredictor(Handler handler, LocationService.LocationListener listener) { - mTimer = handler; + mHandler = handler; mListener = listener; mPredictionCount = 0; @@ -24,7 +32,7 @@ public class LocationPredictor public void run() { if (generatePrediction()) - mTimer.postDelayed(mRunnable, PREDICTION_INTERVAL); + mHandler.postDelayed(mRunnable, PREDICTION_INTERVAL); } }; } @@ -45,13 +53,21 @@ public class LocationPredictor public void reset(Location location) { - mLastLocation = location; + if (location.hasBearing() && location.hasSpeed()) + { + mLastLocation = new Location(location); + mLastLocation.setTime(System.currentTimeMillis()); + mLastLocation.setProvider(LocationService.LOCATION_PREDICTOR_PROVIDER); + } + else + mLastLocation = null; + resetTimer(); } private void onLocationStateModeChangedCallback(final int mode) { - mTimer.post(new Runnable() + mHandler.post(new Runnable() { @Override public void run() @@ -73,9 +89,9 @@ public class LocationPredictor private void resetTimer() { mPredictionCount = 0; - mTimer.removeCallbacks(mRunnable); + mHandler.removeCallbacks(mRunnable); if (mLastLocation != null && mGeneratePredictions) - mTimer.postDelayed(mRunnable, PREDICTION_INTERVAL); + mHandler.postDelayed(mRunnable, PREDICTION_INTERVAL); } private boolean generatePrediction() @@ -87,7 +103,6 @@ public class LocationPredictor { Location info = new Location(mLastLocation); info.setTime(System.currentTimeMillis()); - info.setProvider(LocationService.LOCATION_PREDICTOR_PROVIDER); long elapsedMillis = info.getTime() - mLastLocation.getTime(); @@ -101,13 +116,4 @@ public class LocationPredictor return false; } - - private Runnable mRunnable = null; - private Handler mTimer = null; - - private LocationService.LocationListener mListener = null; - private Location mLastLocation = null; - private boolean mGeneratePredictions = false; - private int mPredictionCount = 0; - private int mConnectionSlot = 0; } diff --git a/iphone/Maps/Classes/LocationPredictor.mm b/iphone/Maps/Classes/LocationPredictor.mm index ef09cf7a61..5edca9e3ac 100644 --- a/iphone/Maps/Classes/LocationPredictor.mm +++ b/iphone/Maps/Classes/LocationPredictor.mm @@ -52,8 +52,17 @@ namespace -(void)reset:(location::GpsInfo const &)info { - m_gpsInfoIsValid = true; - m_lastGpsInfo = info; + if (info.HasSpeed() && info.HasBearing()) + { + m_gpsInfoIsValid = true; + m_lastGpsInfo = info; + m_lastGpsInfo.m_timestamp = my::Timer::LocalTime(); + m_lastGpsInfo.m_source = location::EPredictor; + } + else + { + m_gpsInfoIsValid = false; + } [self resetTimer]; } @@ -87,14 +96,8 @@ namespace location::GpsInfo info = m_lastGpsInfo; info.m_timestamp = my::Timer::LocalTime(); - - double offsetInM = info.m_speed * (info.m_timestamp - m_lastGpsInfo.m_timestamp); - - double angle = my::DegToRad(90.0 - info.m_bearing); - m2::PointD mercatorPt = MercatorBounds::MetresToXY(info.m_longitude, info.m_latitude, info.m_horizontalAccuracy).Center(); - mercatorPt = MercatorBounds::GetSmPoint(mercatorPt, offsetInM * cos(angle), offsetInM * sin(angle)); - info.m_longitude = MercatorBounds::XToLon(mercatorPt.x); - info.m_latitude = MercatorBounds::YToLat(mercatorPt.y); + ::Framework::PredictLocation(info.m_latitude, info.m_longitude, info.m_horizontalAccuracy, info.m_bearing, + info.m_speed, info.m_timestamp - m_lastGpsInfo.m_timestamp); [m_observer onLocationUpdate:info]; } diff --git a/map/framework.cpp b/map/framework.cpp index c1aae23306..cc78694f6b 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1915,6 +1915,18 @@ BookmarkAndCategory Framework::FindBookmark(UserMark const * mark) const return result; } +void Framework::PredictLocation(double & lat, double & lon, double accuracy, + double bearing, double speed, double elapsedSeconds) +{ + double offsetInM = speed * elapsedSeconds; + double angle = my::DegToRad(90.0 - bearing); + + m2::PointD mercatorPt = MercatorBounds::MetresToXY(lon, lat, accuracy).Center(); + mercatorPt = MercatorBounds::GetSmPoint(mercatorPt, offsetInM * cos(angle), offsetInM * sin(angle)); + lon = MercatorBounds::XToLon(mercatorPt.x); + lat = MercatorBounds::YToLat(mercatorPt.y); +} + StringsBundle const & Framework::GetStringsBundle() { return m_stringsBundle; diff --git a/map/framework.hpp b/map/framework.hpp index 185034be62..9e88779578 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -467,6 +467,11 @@ public: PoiMarkPoint * GetAddressMark(m2::PointD const & globalPoint) const; BookmarkAndCategory FindBookmark(UserMark const * mark) const; + /// [in] lat, lon - last known location + /// [out] lat, lon - predicted location + static void PredictLocation(double & lat, double & lon, double accuracy, + double bearing, double speed, double elapsedSeconds); + public: string CodeGe0url(Bookmark const * bmk, bool addName); string CodeGe0url(double lat, double lon, double zoomLevel, string const & name);