diff --git a/android/app/src/main/java/app/organicmaps/car/screens/NavigationScreen.java b/android/app/src/main/java/app/organicmaps/car/screens/NavigationScreen.java index 968b2d86f..64950d908 100644 --- a/android/app/src/main/java/app/organicmaps/car/screens/NavigationScreen.java +++ b/android/app/src/main/java/app/organicmaps/car/screens/NavigationScreen.java @@ -104,7 +104,11 @@ public class NavigationScreen extends BaseMapScreen implements RoutingController public void onAutoDriveEnabled() { Logger.i(TAG); - final JunctionInfo[] points = Framework.nativeGetRouteJunctionPoints(); + + /// @todo Pass maxDistM from RouteSimulationProvider? + /// Result speed between points will be in range (25, 50] km/h (for 1 second update interval). + final double kMaxDistM = 13.9; // 13.9 m/s == 50 km/h + final JunctionInfo[] points = Framework.nativeGetRouteJunctionPoints(kMaxDistM); if (points == null) { Logger.e(TAG, "Navigation has not started yet"); diff --git a/android/sdk/src/main/cpp/app/organicmaps/sdk/Framework.cpp b/android/sdk/src/main/cpp/app/organicmaps/sdk/Framework.cpp index 8df90e5b5..4a7913b47 100644 --- a/android/sdk/src/main/cpp/app/organicmaps/sdk/Framework.cpp +++ b/android/sdk/src/main/cpp/app/organicmaps/sdk/Framework.cpp @@ -1241,16 +1241,32 @@ JNIEXPORT jobject JNICALL Java_app_organicmaps_sdk_Framework_nativeGetRouteFollo return CreateRoutingInfo(env, info, rm); } -JNIEXPORT jobjectArray JNICALL Java_app_organicmaps_sdk_Framework_nativeGetRouteJunctionPoints(JNIEnv * env, jclass) +JNIEXPORT jobjectArray JNICALL Java_app_organicmaps_sdk_Framework_nativeGetRouteJunctionPoints(JNIEnv * env, jclass, + jdouble maxDistM) { - vector junctionPoints; - if (!frm()->GetRoutingManager().RoutingSession().GetRouteJunctionPoints(junctionPoints)) + vector points; + if (!frm()->GetRoutingManager().RoutingSession().GetRouteJunctionPoints(points)) { LOG(LWARNING, ("Can't get the route junction points")); return nullptr; } - return CreateJunctionInfoArray(env, junctionPoints); + vector result; + result.reserve(points.size()); + result.push_back(points[0]); + for (size_t i = 1; i < points.size(); ++i) + { + double const dist = ms::DistanceOnEarth(points[i - 1].ToLatLon(), points[i].ToLatLon()); + if (dist > maxDistM) + { + int const steps = static_cast(dist / maxDistM) + 1; + for (int s = 1; s < steps; ++s) + result.push_back(points[i - 1].Interpolate(points[i], static_cast(s) / steps)); + } + result.push_back(points[i]); + } + + return CreateJunctionInfoArray(env, result); } JNIEXPORT jintArray JNICALL Java_app_organicmaps_sdk_Framework_nativeGenerateRouteAltitudeChartBits( diff --git a/android/sdk/src/main/cpp/app/organicmaps/sdk/routing/JunctionInfo.hpp b/android/sdk/src/main/cpp/app/organicmaps/sdk/routing/JunctionInfo.hpp index e73a3f52a..510bb0854 100644 --- a/android/sdk/src/main/cpp/app/organicmaps/sdk/routing/JunctionInfo.hpp +++ b/android/sdk/src/main/cpp/app/organicmaps/sdk/routing/JunctionInfo.hpp @@ -2,8 +2,6 @@ #include "app/organicmaps/sdk/core/jni_helper.hpp" -#include "geometry/point_with_altitude.hpp" - #include jobjectArray CreateJunctionInfoArray(JNIEnv * env, std::vector const & junctionPoints) @@ -15,7 +13,7 @@ jobjectArray CreateJunctionInfoArray(JNIEnv * env, std::vectorNewObject(junctionClazz, junctionConstructor, mercator::YToLat(point.y), mercator::XToLon(point.x)); + auto const & ll = pointWithAltitude.ToLatLon(); + return env->NewObject(junctionClazz, junctionConstructor, ll.m_lat, ll.m_lon); }); } diff --git a/android/sdk/src/main/java/app/organicmaps/sdk/Framework.java b/android/sdk/src/main/java/app/organicmaps/sdk/Framework.java index 0373e40ad..d0dc92311 100644 --- a/android/sdk/src/main/java/app/organicmaps/sdk/Framework.java +++ b/android/sdk/src/main/java/app/organicmaps/sdk/Framework.java @@ -201,7 +201,8 @@ public class Framework public static native RoutingInfo nativeGetRouteFollowingInfo(); @Nullable - public static native JunctionInfo[] nativeGetRouteJunctionPoints(); + /// @param[in] maxDistM Max distance between points in meters. + public static native JunctionInfo[] nativeGetRouteJunctionPoints(double maxDistM); @Nullable public static native final int[] nativeGenerateRouteAltitudeChartBits(int width, int height, diff --git a/android/sdk/src/main/java/app/organicmaps/sdk/location/RouteSimulationProvider.java b/android/sdk/src/main/java/app/organicmaps/sdk/location/RouteSimulationProvider.java index 329cd319f..3eaf6aece 100644 --- a/android/sdk/src/main/java/app/organicmaps/sdk/location/RouteSimulationProvider.java +++ b/android/sdk/src/main/java/app/organicmaps/sdk/location/RouteSimulationProvider.java @@ -16,6 +16,7 @@ class RouteSimulationProvider extends BaseLocationProvider private final JunctionInfo[] mPoints; private int mCurrentPoint = 0; + private Location mPrev = null; private boolean mActive = false; RouteSimulationProvider(@NonNull Context context, @NonNull Listener listener, JunctionInfo[] points) @@ -56,9 +57,20 @@ class RouteSimulationProvider extends BaseLocationProvider location.setLatitude(mPoints[mCurrentPoint].mLat); location.setLongitude(mPoints[mCurrentPoint].mLon); location.setAccuracy(1.0f); + + if (mPrev != null) + { + location.setSpeed(mPrev.distanceTo(location) / (INTERVAL_MS / 1000)); + location.setBearing(mPrev.bearingTo(location)); + } + location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos()); + location.setTime(System.currentTimeMillis()); + mListener.onLocationChanged(location); mCurrentPoint += 1; + mPrev = location; + UiThread.runLater(this::nextPoint, INTERVAL_MS); } } diff --git a/libs/geometry/point_with_altitude.cpp b/libs/geometry/point_with_altitude.cpp index d76210c5f..8674d786f 100644 --- a/libs/geometry/point_with_altitude.cpp +++ b/libs/geometry/point_with_altitude.cpp @@ -1,6 +1,8 @@ #include "geometry/point_with_altitude.hpp" -#include "std/boost_container_hash.hpp" +#include "geometry/mercator.hpp" + +#include #include @@ -26,6 +28,11 @@ bool PointWithAltitude::operator<(PointWithAltitude const & r) const return m_altitude < r.m_altitude; } +ms::LatLon PointWithAltitude::ToLatLon() const +{ + return ms::LatLon(mercator::YToLat(m_point.y), mercator::XToLon(m_point.x)); +} + std::string DebugPrint(PointWithAltitude const & r) { std::ostringstream ss; diff --git a/libs/geometry/point_with_altitude.hpp b/libs/geometry/point_with_altitude.hpp index 91892eab6..7007e5fb6 100644 --- a/libs/geometry/point_with_altitude.hpp +++ b/libs/geometry/point_with_altitude.hpp @@ -1,7 +1,10 @@ #pragma once +#include "geometry/latlon.hpp" #include "geometry/point2d.hpp" +#include "base/math.hpp" + #include #include #include @@ -26,11 +29,19 @@ public: bool operator<(PointWithAltitude const & r) const; m2::PointD const & GetPoint() const { return m_point; } + ms::LatLon ToLatLon() const; Altitude GetAltitude() const { return m_altitude; } void SetPoint(m2::PointD const & point) { m_point = point; } void SetAltitude(Altitude altitude) { m_altitude = altitude; } + /// @param[in] f in range [0, 1] + PointWithAltitude Interpolate(PointWithAltitude const & to, double f) const + { + return PointWithAltitude(m_point + (to.m_point - m_point) * f, + math::iround(m_altitude + (to.m_altitude - m_altitude) * f)); + } + private: friend std::string DebugPrint(PointWithAltitude const & r);