From 2c812051122108825130618880c5f04c91fa786d Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Thu, 15 Jun 2017 14:33:01 +0300 Subject: [PATCH] Fixed interface between iOS/Android and routing manager --- android/jni/com/mapswithme/maps/Framework.cpp | 72 +++++++--------- .../src/com/mapswithme/maps/Framework.java | 18 ++-- .../maps/routing/RouteMarkData.java | 31 +++++++ .../maps/routing/RoutingController.java | 30 +++---- iphone/Maps/Core/Routing/MWMRouter.mm | 34 +++++--- map/routing_manager.cpp | 79 +++++++++-------- map/routing_manager.hpp | 18 ++-- map/routing_mark.cpp | 85 ++++++++++--------- map/routing_mark.hpp | 38 ++++++--- qt/draw_widget.cpp | 16 +++- 10 files changed, 250 insertions(+), 171 deletions(-) create mode 100644 android/src/com/mapswithme/maps/routing/RouteMarkData.java diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index 42bf68e908..bab9af98f6 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -913,14 +913,9 @@ Java_com_mapswithme_maps_Framework_nativeCloseRouting(JNIEnv * env, jclass) } JNIEXPORT void JNICALL -Java_com_mapswithme_maps_Framework_nativeBuildRoute(JNIEnv * env, jclass, - jdouble startLat, jdouble startLon, - jdouble finishLat, jdouble finishLon, - jboolean isP2P) +Java_com_mapswithme_maps_Framework_nativeBuildRoute(JNIEnv * env, jclass) { - frm()->GetRoutingManager().BuildRoute(MercatorBounds::FromLatLon(startLat, startLon), - MercatorBounds::FromLatLon(finishLat, finishLon), isP2P, - 0 /* timeoutSec */); + frm()->GetRoutingManager().BuildRoute(0 /* timeoutSec */); } JNIEXPORT void JNICALL @@ -1151,43 +1146,28 @@ Java_com_mapswithme_maps_Framework_nativeGetBestRouter(JNIEnv * env, jclass, MercatorBounds::FromLatLon(srcLat, srcLon), MercatorBounds::FromLatLon(dstLat, dstLon))); } -void ExtractRoutePointInfo(JNIEnv * env, jobject routePointInfo, - RouteMarkType & markType, int8_t & intermediateIndex) -{ - static jclass const clazz = env->GetObjectClass(routePointInfo); - ASSERT(clazz, ()); - static jfieldID const markTypeField = env->GetFieldID(clazz, "mMarkType", "I"); - ASSERT(markTypeField, ()); - static jfieldID const intermediateIndexField = env->GetFieldID(clazz, "mIntermediateIndex", "I"); - ASSERT(intermediateIndexField, ()); - markType = static_cast(env->GetIntField(routePointInfo, markTypeField)); - intermediateIndex = static_cast(env->GetIntField(routePointInfo, intermediateIndexField)); -} - JNIEXPORT void JNICALL -Java_com_mapswithme_maps_Framework_nativeAddRoutePoint(JNIEnv * env, jclass, - jdouble lat, jdouble lon, +Java_com_mapswithme_maps_Framework_nativeAddRoutePoint(JNIEnv * env, jclass, jstring name, + jint markType, jint intermediateIndex, jboolean isMyPosition, - jobject routePointInfo) + jdouble lat, jdouble lon) { - RouteMarkType markType; - int8_t intermediateIndex; - ExtractRoutePointInfo(env, routePointInfo, markType, intermediateIndex); + RouteMarkData data; + data.m_name = jni::ToNativeString(env, name); + data.m_pointType = static_cast(markType); + data.m_intermediateIndex = static_cast(intermediateIndex); + data.m_isMyPosition = static_cast(isMyPosition); + data.m_position = m2::PointD(MercatorBounds::FromLatLon(lat, lon)); - frm()->GetRoutingManager().AddRoutePoint(m2::PointD(MercatorBounds::FromLatLon(lat, lon)), - static_cast(isMyPosition), - markType, intermediateIndex); + frm()->GetRoutingManager().AddRoutePoint(std::move(data)); } JNIEXPORT void JNICALL Java_com_mapswithme_maps_Framework_nativeRemoveRoutePoint(JNIEnv * env, jclass, - jobject routePointInfo) + jint markType, jint intermediateIndex) { - RouteMarkType markType; - int8_t intermediateIndex; - ExtractRoutePointInfo(env, routePointInfo, markType, intermediateIndex); - - frm()->GetRoutingManager().RemoveRoutePoint(markType, intermediateIndex); + frm()->GetRoutingManager().RemoveRoutePoint(static_cast(markType), + static_cast(intermediateIndex)); } JNIEXPORT jboolean JNICALL @@ -1201,16 +1181,24 @@ Java_com_mapswithme_maps_Framework_nativeGetRoutePoints(JNIEnv * env, jclass) { auto const points = frm()->GetRoutingManager().GetRoutePoints(); - static jclass const pointClazz = jni::GetGlobalClassRef(env, "com/mapswithme/maps/api/RoutePoint"); - // Java signature : RoutePoint(double lat, double lon, String name) + static jclass const pointClazz = jni::GetGlobalClassRef(env, + "com/mapswithme/maps/routing/RouteMarkData"); + // Java signature : RouteMarkData(String name, @RoutePointInfo.RouteMarkType int pointType, + // int intermediateIndex, boolean isVisible, boolean isMyPosition, + // boolean isPassed, double lat, double lon) static jmethodID const pointConstructor = jni::GetConstructorID(env, pointClazz, - "(DDLjava/lang/String;)V"); - return jni::ToJavaArray(env, pointClazz, points, [&](JNIEnv * env, m2::PointD const & pt) + "(Ljava/lang/String;IIZZZDD)V"); + return jni::ToJavaArray(env, pointClazz, points, [&](JNIEnv * env, RouteMarkData const & data) { - jni::TScopedLocalRef const name(env, jni::ToJavaString(env, "")); + jni::TScopedLocalRef const name(env, jni::ToJavaString(env, data.m_name)); return env->NewObject(pointClazz, pointConstructor, - MercatorBounds::YToLat(pt.y), - MercatorBounds::XToLon(pt.x), name.get()); + name.get(), static_cast(data.m_pointType), + static_cast(data.m_intermediateIndex), + static_cast(data.m_isVisible), + static_cast(data.m_isMyPosition), + static_cast(data.m_isPassed), + MercatorBounds::YToLat(data.m_position.y), + MercatorBounds::XToLon(data.m_position.x)); }); } diff --git a/android/src/com/mapswithme/maps/Framework.java b/android/src/com/mapswithme/maps/Framework.java index cbb273570c..7aff6cc411 100644 --- a/android/src/com/mapswithme/maps/Framework.java +++ b/android/src/com/mapswithme/maps/Framework.java @@ -16,6 +16,7 @@ import com.mapswithme.maps.api.RoutePoint; import com.mapswithme.maps.bookmarks.data.DistanceAndAzimut; import com.mapswithme.maps.bookmarks.data.MapObject; import com.mapswithme.maps.location.LocationHelper; +import com.mapswithme.maps.routing.RouteMarkData; import com.mapswithme.maps.routing.RoutePointInfo; import com.mapswithme.maps.routing.RoutingInfo; import com.mapswithme.util.Constants; @@ -223,8 +224,7 @@ public class Framework public static native void nativeCloseRouting(); - public static native void nativeBuildRoute(double startLat, double startLon, - double finishLat, double finishLon, boolean isP2P); + public static native void nativeBuildRoute(); public static native void nativeRemoveRoute(); @@ -271,14 +271,18 @@ public class Framework @RouterType public static native int nativeGetLastUsedRouter(); @RouterType - public static native int nativeGetBestRouter(double srcLat, double srcLon, double dstLat, double dstLon); + public static native int nativeGetBestRouter(double srcLat, double srcLon, + double dstLat, double dstLon); - public static native void nativeAddRoutePoint(double lat, double lon, boolean isMyPosition, - @NonNull RoutePointInfo routePointInfo); - public static native void nativeRemoveRoutePoint(@NonNull RoutePointInfo routePointInfo); + public static native void nativeAddRoutePoint(String name, + @RoutePointInfo.RouteMarkType int markType, + int intermediateIndex, boolean isMyPosition, + double lat, double lon); + public static native void nativeRemoveRoutePoint(@RoutePointInfo.RouteMarkType int markType, + int intermediateIndex); public static native boolean nativeCouldAddIntermediatePoint(); @NonNull - public static native RoutePoint[] nativeGetRoutePoints(); + public static native RouteMarkData[] nativeGetRoutePoints(); /** * Registers all maps(.mwms). Adds them to the models, generates indexes and does all necessary stuff. diff --git a/android/src/com/mapswithme/maps/routing/RouteMarkData.java b/android/src/com/mapswithme/maps/routing/RouteMarkData.java new file mode 100644 index 0000000000..fb893df588 --- /dev/null +++ b/android/src/com/mapswithme/maps/routing/RouteMarkData.java @@ -0,0 +1,31 @@ +package com.mapswithme.maps.routing; + +/** + * Represents RouteMarkData from core. + */ +public class RouteMarkData +{ + public final String mName; + @RoutePointInfo.RouteMarkType + public final int mPointType; + public final int mIntermediateIndex; + public final boolean mIsVisible; + public final boolean mIsMyPosition; + public final boolean mIsPassed; + public final double mLat; + public final double mLon; + + public RouteMarkData(String name, @RoutePointInfo.RouteMarkType int pointType, + int intermediateIndex, boolean isVisible, boolean isMyPosition, + boolean isPassed, double lat, double lon) + { + mName = name; + mPointType = pointType; + mIntermediateIndex = intermediateIndex; + mIsVisible = isVisible; + mIsMyPosition = isMyPosition; + mIsPassed = isPassed; + mLat = lat; + mLon = lon; + } +} diff --git a/android/src/com/mapswithme/maps/routing/RoutingController.java b/android/src/com/mapswithme/maps/routing/RoutingController.java index 030361e153..547947baa7 100644 --- a/android/src/com/mapswithme/maps/routing/RoutingController.java +++ b/android/src/com/mapswithme/maps/routing/RoutingController.java @@ -277,7 +277,7 @@ public class RoutingController { Framework.nativeRemoveRoute(); - RoutePoint[] routePoints = Framework.nativeGetRoutePoints(); + RouteMarkData[] routePoints = Framework.nativeGetRoutePoints(); if (routePoints.length < 2) { setBuildState(BuildState.NONE); @@ -303,18 +303,12 @@ public class RoutingController setBuildState(BuildState.BUILDING); updatePlan(); - boolean isP2P = !MapObject.isOfType(MapObject.MY_POSITION, mStartPoint) && - !MapObject.isOfType(MapObject.MY_POSITION, mEndPoint); - Statistics.INSTANCE.trackRouteBuild(mLastRouterType, mStartPoint, mEndPoint); org.alohalytics.Statistics.logEvent(AlohaHelper.ROUTING_BUILD, new String[]{Statistics.EventParam.FROM, Statistics.getPointType(mStartPoint), Statistics.EventParam.TO, Statistics.getPointType(mEndPoint)}); - // TODO: multipoint route must be here soon. - RoutePoint from = routePoints[0]; - RoutePoint to = routePoints[routePoints.length - 1]; - Framework.nativeBuildRoute(from.mLat, from.mLon, to.mLat, to.mLon, isP2P); + Framework.nativeBuildRoute(); } private void completeUberRequest() @@ -440,9 +434,9 @@ public class RoutingController public void addStop(@NonNull MapObject mapObject) { - RoutePointInfo info = new RoutePointInfo(RoutePointInfo.ROUTE_MARK_INTERMEDIATE, 0); - Framework.nativeAddRoutePoint(mapObject.getLat(), mapObject.getLon(), - MapObject.isOfType(MapObject.MY_POSITION, mapObject), info); + Framework.nativeAddRoutePoint("", RoutePointInfo.ROUTE_MARK_INTERMEDIATE, 0, + MapObject.isOfType(MapObject.MY_POSITION, mapObject), + mapObject.getLat(), mapObject.getLon()); build(); if (mContainer != null) mContainer.onAddedStop(); @@ -454,7 +448,7 @@ public class RoutingController if (info == null) throw new AssertionError("A stop point must have the route point info!"); - Framework.nativeRemoveRoutePoint(info); + Framework.nativeRemoveRoutePoint(info.mMarkType, info.mIntermediateIndex); if (info.isFinishPoint()) mEndPoint = null; if (info.isStartPoint()) @@ -657,24 +651,24 @@ public class RoutingController { if (mStartPoint == null) { - Framework.nativeRemoveRoutePoint(new RoutePointInfo(RoutePointInfo.ROUTE_MARK_START, 0)); + Framework.nativeRemoveRoutePoint(RoutePointInfo.ROUTE_MARK_START, 0); } else { - Framework.nativeAddRoutePoint(mStartPoint.getLat(), mStartPoint.getLon(), + Framework.nativeAddRoutePoint("", RoutePointInfo.ROUTE_MARK_START, 0, MapObject.isOfType(MapObject.MY_POSITION, mStartPoint), - new RoutePointInfo(RoutePointInfo.ROUTE_MARK_START, 0)); + mStartPoint.getLat(), mStartPoint.getLon()); } if (mEndPoint == null) { - Framework.nativeRemoveRoutePoint(new RoutePointInfo(RoutePointInfo.ROUTE_MARK_FINISH, 0)); + Framework.nativeRemoveRoutePoint(RoutePointInfo.ROUTE_MARK_FINISH, 0); } else { - Framework.nativeAddRoutePoint(mEndPoint.getLat(), mEndPoint.getLon(), + Framework.nativeAddRoutePoint("", RoutePointInfo.ROUTE_MARK_FINISH, 0, MapObject.isOfType(MapObject.MY_POSITION, mEndPoint), - new RoutePointInfo(RoutePointInfo.ROUTE_MARK_FINISH, 0)); + mEndPoint.getLat(), mEndPoint.getLon()); } } diff --git a/iphone/Maps/Core/Routing/MWMRouter.mm b/iphone/Maps/Core/Routing/MWMRouter.mm index b2fa26dedb..5e893094ea 100644 --- a/iphone/Maps/Core/Routing/MWMRouter.mm +++ b/iphone/Maps/Core/Routing/MWMRouter.mm @@ -148,13 +148,19 @@ m2::PointD getMercator(MWMRoutePoint * p) auto & rm = GetFramework().GetRoutingManager(); if (self.startPoint.isValid) { - rm.AddRoutePoint(getMercator(self.startPoint), self.startPoint.isMyPosition, - RouteMarkType::Start); + RouteMarkData pt; + pt.m_pointType = RouteMarkType::Start; + pt.m_isMyPosition = self.startPoint.isMyPosition; + pt.m_position = getMercator(self.startPoint); + rm.AddRoutePoint(std::move(pt)); } if (self.finishPoint.isValid) { - rm.AddRoutePoint(getMercator(self.finishPoint), self.finishPoint.isMyPosition, - RouteMarkType::Finish); + RouteMarkData pt; + pt.m_pointType = RouteMarkType::Finish; + pt.m_isMyPosition = self.finishPoint.isMyPosition; + pt.m_position = getMercator(self.finishPoint); + rm.AddRoutePoint(std::move(pt)); } } @@ -175,11 +181,11 @@ m2::PointD getMercator(MWMRoutePoint * p) { // At least 2 points exist, one of them may (or may not) be my position. self.startPoint = rm.IsMyPosition(RouteMarkType::Start) ? - routePoint(points.front()) : - routePoint(points.front(), nil); + routePoint(points.front().m_position) : + routePoint(points.front().m_position, nil); self.finishPoint = rm.IsMyPosition(RouteMarkType::Finish) ? - routePoint(points.back()) : - routePoint(points.back(), nil); + routePoint(points.back().m_position) : + routePoint(points.back().m_position, nil); } } @@ -205,8 +211,12 @@ m2::PointD getMercator(MWMRoutePoint * p) - (void)addIntermediatePointAndRebuild:(MWMRoutePoint *)point intermediateIndex:(int)intermediateIndex { - GetFramework().GetRoutingManager().AddRoutePoint(getMercator(point), point.isMyPosition, - RouteMarkType::Intermediate, intermediateIndex); + RouteMarkData pt; + pt.m_pointType = RouteMarkType::Intermediate; + pt.m_position = getMercator(point); + pt.m_intermediateIndex = intermediateIndex; + pt.m_isMyPosition = static_cast(point.isMyPosition); + GetFramework().GetRoutingManager().AddRoutePoint(std::move(pt)); [self rebuildWithBestRouter:NO]; } @@ -275,9 +285,9 @@ m2::PointD getMercator(MWMRoutePoint * p) // Taxi can't be used as best router. if (bestRouter && ![[self class] isTaxi]) - self.type = routerType(rm.GetBestRouter(points.front(), points.back())); + self.type = routerType(rm.GetBestRouter(points.front().m_position, points.back().m_position)); - rm.BuildRoute(points.front(), points.back(), isP2P, 0 /* timeoutSec */); + rm.BuildRoute(0 /* timeoutSec */); [mapViewControlsManager onRouteRebuild]; } diff --git a/map/routing_manager.cpp b/map/routing_manager.cpp index 49c8cbbfc1..f07fd3cdb9 100644 --- a/map/routing_manager.cpp +++ b/map/routing_manager.cpp @@ -322,18 +322,13 @@ bool RoutingManager::IsMyPosition(RouteMarkType type, int8_t intermediateIndex) return mark != nullptr ? mark->IsMyPosition() : false; } -std::vector RoutingManager::GetRoutePoints() const +std::vector RoutingManager::GetRoutePoints() const { - std::vector result; + std::vector result; UserMarkControllerGuard guard(*m_bmManager, UserMarkType::ROUTING_MARK); RoutePointsLayout routePoints(guard.m_controller); - RouteMarkPoint * start = routePoints.GetRoutePoint(RouteMarkType::Start); - RouteMarkPoint * finish = routePoints.GetRoutePoint(RouteMarkType::Finish); - if (start != nullptr && finish != nullptr) - { - result.push_back(start->GetPivot()); - result.push_back(finish->GetPivot()); - } + for (auto const & p : routePoints.GetRoutePoints()) + result.push_back(p->GetMarkData()); return result; } @@ -346,23 +341,18 @@ bool RoutingManager::CouldAddIntermediatePoint() const static_cast(RoutePointsLayout::kMaxIntermediatePointsCount + 2); } -void RoutingManager::AddRoutePoint(m2::PointD const & pt, bool isMyPosition, - RouteMarkType type, int8_t intermediateIndex) +void RoutingManager::AddRoutePoint(RouteMarkData && markData) { ASSERT(m_bmManager != nullptr, ()); UserMarkControllerGuard guard(*m_bmManager, UserMarkType::ROUTING_MARK); RoutePointsLayout routePoints(guard.m_controller); // Always replace start and finish points. - if (type == RouteMarkType::Start || type == RouteMarkType::Finish) - routePoints.RemoveRoutePoint(type, intermediateIndex); + if (markData.m_pointType == RouteMarkType::Start || markData.m_pointType == RouteMarkType::Finish) + routePoints.RemoveRoutePoint(markData.m_pointType); - RouteMarkPoint * mark = routePoints.AddRoutePoint(pt, type, intermediateIndex); - if (mark != nullptr) - { - mark->SetIsVisible(!isMyPosition); - mark->SetIsMyPosition(isMyPosition); - } + markData.m_isVisible = !markData.m_isMyPosition; + routePoints.AddRoutePoint(std::move(markData)); } void RoutingManager::RemoveRoutePoint(RouteMarkType type, int8_t intermediateIndex) @@ -391,25 +381,37 @@ void RoutingManager::GenerateTurnNotifications(std::vector & turnNo return m_routingSession.GenerateTurnNotifications(turnNotifications); } -void RoutingManager::BuildRoute(m2::PointD const & finish, uint32_t timeoutSec) +void RoutingManager::BuildRoute(uint32_t timeoutSec) { ASSERT_THREAD_CHECKER(m_threadChecker, ("BuildRoute")); ASSERT(m_drapeEngine != nullptr, ()); - m2::PointD start; - if (!m_drapeEngine->GetMyPosition(start)) + auto routePoints = GetRoutePoints(); + if (routePoints.size() < 2) { - CallRouteBuilded(IRouter::NoCurrentPosition, storage::TCountriesVec()); + if (routePoints.empty() || routePoints.back().m_pointType != RouteMarkType::Finish) + CallRouteBuilded(IRouter::EndPointNotFound, storage::TCountriesVec()); + else + CallRouteBuilded(IRouter::StartPointNotFound, storage::TCountriesVec()); return; } - BuildRoute(start, finish, false /* isP2P */, timeoutSec); -} -void RoutingManager::BuildRoute(m2::PointD const & start, m2::PointD const & finish, bool isP2P, - uint32_t timeoutSec) -{ - ASSERT_THREAD_CHECKER(m_threadChecker, ("BuildRoute")); - ASSERT(m_drapeEngine != nullptr, ()); + // Update my position. + for (auto & p : routePoints) + { + if (!p.m_isMyPosition) + continue; + + m2::PointD myPos; + if (!m_drapeEngine->GetMyPosition(myPos)) + { + CallRouteBuilded(IRouter::NoCurrentPosition, storage::TCountriesVec()); + return; + } + p.m_position = myPos; + } + + bool const isP2P = !routePoints.front().m_isMyPosition && !routePoints.back().m_isMyPosition; // Send tag to Push Woosh. { @@ -440,15 +442,24 @@ void RoutingManager::BuildRoute(m2::PointD const & start, m2::PointD const & fin // Show preview. if (m_drapeEngine != nullptr) { - m_drapeEngine->AddRoutePreviewSegment(start, finish); - m2::RectD rect(start, finish); + m2::RectD rect; + for (size_t pointIndex = 0; pointIndex + 1 < routePoints.size(); pointIndex++) + { + rect.Add(routePoints[pointIndex].m_position); + rect.Add(routePoints[pointIndex + 1].m_position); + m_drapeEngine->AddRoutePreviewSegment(routePoints[pointIndex].m_position, + routePoints[pointIndex + 1].m_position); + } rect.Scale(kRouteScaleMultiplier); m_drapeEngine->SetModelViewRect(rect, true /* applyRotation */, -1 /* zoom */, true /* isAnim */); } - m_routingSession.SetUserCurrentPosition(start); - m_routingSession.BuildRoute(start, finish, timeoutSec); + m_routingSession.SetUserCurrentPosition(routePoints.front().m_position); + + //TODO: build using all points. + m_routingSession.BuildRoute(routePoints.front().m_position, + routePoints.back().m_position, timeoutSec); } void RoutingManager::SetUserCurrentPosition(m2::PointD const & position) diff --git a/map/routing_manager.hpp b/map/routing_manager.hpp index 1bdb42e991..6ca6213a4f 100644 --- a/map/routing_manager.hpp +++ b/map/routing_manager.hpp @@ -37,6 +37,16 @@ class NumMwmIds; class Index; +struct RoutePointInfo +{ + std::string m_name; + RouteMarkType m_markType = RouteMarkType::Start; + int8_t m_intermediateIndex = 0; + bool m_isPassed = false; + bool m_isMyPosition = false; + m2::PointD m_position; +}; + class RoutingManager final { public: @@ -83,9 +93,7 @@ public: bool IsRouteFinished() const { return m_routingSession.IsFinished(); } bool IsOnRoute() const { return m_routingSession.IsOnRoute(); } bool IsRoutingFollowing() const { return m_routingSession.IsFollowing(); } - void BuildRoute(m2::PointD const & finish, uint32_t timeoutSec); - void BuildRoute(m2::PointD const & start, m2::PointD const & finish, bool isP2P, - uint32_t timeoutSec); + void BuildRoute(uint32_t timeoutSec); void SetUserCurrentPosition(m2::PointD const & position); void ResetRoutingSession() { m_routingSession.Reset(); } // FollowRoute has a bug where the router follows the route even if the method hads't been called. @@ -155,7 +163,7 @@ public: /// GenerateTurnNotifications shall be called by the client when a new position is available. void GenerateTurnNotifications(std::vector & turnNotifications); - void AddRoutePoint(m2::PointD const & pt, bool isMyPosition, RouteMarkType type, int8_t intermediateIndex = 0); + void AddRoutePoint(RouteMarkData && markData); void RemoveRoutePoint(RouteMarkType type, int8_t intermediateIndex = 0); void MoveRoutePoint(RouteMarkType currentType, int8_t currentIntermediateIndex, RouteMarkType targetType, int8_t targetIntermediateIndex); @@ -202,7 +210,7 @@ public: int32_t & minRouteAltitude, int32_t & maxRouteAltitude, measurement_utils::Units & altitudeUnits) const; - std::vector GetRoutePoints() const; + std::vector GetRoutePoints() const; private: void InsertRoute(routing::Route const & route); diff --git a/map/routing_mark.cpp b/map/routing_mark.cpp index fbda70f7fa..6073b950f0 100644 --- a/map/routing_mark.cpp +++ b/map/routing_mark.cpp @@ -2,45 +2,28 @@ #include -RouteMarkPoint::RouteMarkPoint(const m2::PointD & ptOrg, UserMarkContainer * container) +RouteMarkPoint::RouteMarkPoint(m2::PointD const & ptOrg, + UserMarkContainer * container) : UserMark(ptOrg, container) -{} - -bool RouteMarkPoint::IsVisible() const { - return m_isVisible; -} - -void RouteMarkPoint::SetIsVisible(bool isVisible) -{ - m_isVisible = isVisible; + m_markData.m_position = ptOrg; } dp::Anchor RouteMarkPoint::GetAnchor() const { - if (m_pointType == RouteMarkType::Finish) + if (m_markData.m_pointType == RouteMarkType::Finish) return dp::Bottom; return dp::Center; } -void RouteMarkPoint::SetIsMyPosition(bool isMyPosition) -{ - m_isMyPosition = isMyPosition; -} - -bool RouteMarkPoint::IsMyPosition() const -{ - return m_isMyPosition; -} - std::string RouteMarkPoint::GetSymbolName() const { - switch (m_pointType) + switch (m_markData.m_pointType) { case RouteMarkType::Start: return "route-point-start"; case RouteMarkType::Intermediate: { - switch (m_intermediateIndex) + switch (m_markData.m_intermediateIndex) { case 0: return "route-point-a"; case 1: return "route-point-b"; @@ -67,16 +50,15 @@ RoutePointsLayout::RoutePointsLayout(UserMarksController & routeMarks) : m_routeMarks(routeMarks) {} -RouteMarkPoint * RoutePointsLayout::AddRoutePoint(m2::PointD const & ptOrg, RouteMarkType type, - int8_t intermediateIndex) +RouteMarkPoint * RoutePointsLayout::AddRoutePoint(RouteMarkData && data) { if (m_routeMarks.GetUserMarkCount() == kMaxIntermediatePointsCount + 2) return nullptr; - RouteMarkPoint * sameTypePoint = GetRoutePoint(type, intermediateIndex); + RouteMarkPoint * sameTypePoint = GetRoutePoint(data.m_pointType, data.m_intermediateIndex); if (sameTypePoint != nullptr) { - if (type == RouteMarkType::Finish) + if (data.m_pointType == RouteMarkType::Finish) { int const intermediatePointsCount = std::max(static_cast(m_routeMarks.GetUserMarkCount()) - 2, 0); sameTypePoint->SetRoutePointType(RouteMarkType::Intermediate); @@ -84,7 +66,7 @@ RouteMarkPoint * RoutePointsLayout::AddRoutePoint(m2::PointD const & ptOrg, Rout } else { - int const offsetIndex = type == RouteMarkType::Start ? 0 : intermediateIndex; + int const offsetIndex = data.m_pointType == RouteMarkType::Start ? 0 : data.m_intermediateIndex; ForEachIntermediatePoint([offsetIndex](RouteMarkPoint * mark) { @@ -92,21 +74,19 @@ RouteMarkPoint * RoutePointsLayout::AddRoutePoint(m2::PointD const & ptOrg, Rout mark->SetIntermediateIndex(static_cast(mark->GetIntermediateIndex() + 1)); }); - if (type == RouteMarkType::Start) + if (data.m_pointType == RouteMarkType::Start) { sameTypePoint->SetRoutePointType(RouteMarkType::Intermediate); sameTypePoint->SetIntermediateIndex(0); } } } - RouteMarkPoint * newPoint = static_cast(m_routeMarks.CreateUserMark(ptOrg)); - newPoint->SetRoutePointType(type); - newPoint->SetIntermediateIndex(intermediateIndex); + RouteMarkPoint * newPoint = static_cast(m_routeMarks.CreateUserMark(data.m_position)); + newPoint->SetMarkData(std::move(data)); return newPoint; } - bool RoutePointsLayout::RemoveRoutePoint(RouteMarkType type, int8_t intermediateIndex) { RouteMarkPoint * point = nullptr; @@ -170,14 +150,13 @@ bool RoutePointsLayout::MoveRoutePoint(RouteMarkType currentType, int8_t current if (point == nullptr) return false; - m2::PointD const pt = point->GetPivot(); - bool const isVisible = point->IsVisible(); - bool const isMyPosition = point->IsMyPosition(); + RouteMarkData data = point->GetMarkData(); + data.m_pointType = destType; + data.m_intermediateIndex = destIntermediateIndex; RemoveRoutePoint(currentType, currentIntermediateIndex); - RouteMarkPoint * point2 = AddRoutePoint(pt, destType, destIntermediateIndex); - point2->SetIsVisible(isVisible); - point2->SetIsMyPosition(isMyPosition); + + AddRoutePoint(std::move(data)); return true; } @@ -202,6 +181,34 @@ RouteMarkPoint * RoutePointsLayout::GetRoutePoint(RouteMarkType type, int8_t int return nullptr; } +std::vector RoutePointsLayout::GetRoutePoints() +{ + std::vector points; + points.reserve(m_routeMarks.GetUserMarkCount()); + RouteMarkPoint * startPoint = nullptr; + RouteMarkPoint * finishPoint = nullptr; + for (size_t i = 0, sz = m_routeMarks.GetUserMarkCount(); i < sz; ++i) + { + RouteMarkPoint * p = static_cast(m_routeMarks.GetUserMarkForEdit(i)); + ASSERT(p != nullptr, ()); + if (p->GetRoutePointType() == RouteMarkType::Start) + startPoint = p; + else if (p->GetRoutePointType() == RouteMarkType::Finish) + finishPoint = p; + else + points.push_back(p); + } + std::sort(points.begin(), points.end(), [](RouteMarkPoint const * p1, RouteMarkPoint const * p2) + { + return p1->GetIntermediateIndex() < p2->GetIntermediateIndex(); + }); + if (startPoint != nullptr) + points.insert(points.begin(), startPoint); + if (finishPoint != nullptr) + points.push_back(finishPoint); + return points; +} + void RoutePointsLayout::ForEachIntermediatePoint(TRoutePointCallback const & fn) { for (size_t i = 0, sz = m_routeMarks.GetUserMarkCount(); i < sz; ++i) diff --git a/map/routing_mark.hpp b/map/routing_mark.hpp index 9393907903..5fb7b22e70 100644 --- a/map/routing_mark.hpp +++ b/map/routing_mark.hpp @@ -11,34 +11,45 @@ enum class RouteMarkType : uint8_t Finish = 2 }; +struct RouteMarkData +{ + std::string m_name; + RouteMarkType m_pointType = RouteMarkType::Start; + int8_t m_intermediateIndex = 0; + bool m_isVisible = true; + bool m_isMyPosition = false; + bool m_isPassed = false; + m2::PointD m_position; +}; + class RouteMarkPoint : public UserMark { public: RouteMarkPoint(m2::PointD const & ptOrg, UserMarkContainer * container); virtual ~RouteMarkPoint() {} - bool IsVisible() const override; - void SetIsVisible(bool isVisible); + bool IsVisible() const override { return m_markData.m_isVisible; } + void SetIsVisible(bool isVisible) { m_markData.m_isVisible = isVisible; } dp::Anchor GetAnchor() const override; std::string GetSymbolName() const override; UserMark::Type GetMarkType() const override { return Type::ROUTING; } - RouteMarkType GetRoutePointType() const { return m_pointType; } - void SetRoutePointType(RouteMarkType type) { m_pointType = type; } + RouteMarkType GetRoutePointType() const { return m_markData.m_pointType; } + void SetRoutePointType(RouteMarkType type) { m_markData.m_pointType = type; } - void SetIntermediateIndex(int8_t index) { m_intermediateIndex = index; } - int8_t GetIntermediateIndex() const { return m_intermediateIndex; } + void SetIntermediateIndex(int8_t index) { m_markData.m_intermediateIndex = index; } + int8_t GetIntermediateIndex() const { return m_markData.m_intermediateIndex; } - void SetIsMyPosition(bool isMyPosition); - bool IsMyPosition() const; + void SetIsMyPosition(bool isMyPosition) { m_markData.m_isMyPosition = isMyPosition;} + bool IsMyPosition() const { return m_markData.m_isMyPosition; } + + RouteMarkData const & GetMarkData() const { return m_markData; } + void SetMarkData(RouteMarkData && data) { m_markData = std::move(data); } private: - RouteMarkType m_pointType; - int8_t m_intermediateIndex = 0; - bool m_isVisible = true; - bool m_isMyPosition = false; + RouteMarkData m_markData; }; class RouteUserMarkContainer : public UserMarkContainer @@ -56,8 +67,9 @@ public: RoutePointsLayout(UserMarksController & routeMarks); + RouteMarkPoint * AddRoutePoint(RouteMarkData && data); RouteMarkPoint * GetRoutePoint(RouteMarkType type, int8_t intermediateIndex = 0); - RouteMarkPoint * AddRoutePoint(m2::PointD const & ptOrg, RouteMarkType type, int8_t intermediateIndex = 0); + std::vector GetRoutePoints(); bool RemoveRoutePoint(RouteMarkType type, int8_t intermediateIndex = 0); bool MoveRoutePoint(RouteMarkType currentType, int8_t currentIntermediateIndex, RouteMarkType destType, int8_t destIntermediateIndex); diff --git a/qt/draw_widget.cpp b/qt/draw_widget.cpp index 4c77b84c23..409b4e1c70 100644 --- a/qt/draw_widget.cpp +++ b/qt/draw_widget.cpp @@ -328,9 +328,23 @@ void DrawWidget::SubmitRoutingPoint(m2::PointD const & pt) { auto & routingManager = m_framework.GetRoutingManager(); if (routingManager.IsRoutingActive()) + { routingManager.CloseRouting(true /* remove route points */); + } else - routingManager.BuildRoute(m_framework.PtoG(pt), 0 /* timeoutSec */); + { + RouteMarkData startPoint; + startPoint.m_pointType = RouteMarkType::Start; + startPoint.m_isMyPosition = true; + routingManager.AddRoutePoint(std::move(startPoint)); + + RouteMarkData endPoint; + endPoint.m_pointType = RouteMarkType::Finish; + endPoint.m_position = m_framework.PtoG(pt); + routingManager.AddRoutePoint(std::move(endPoint)); + + routingManager.BuildRoute(0 /* timeoutSec */); + } } void DrawWidget::ShowPlacePage(place_page::Info const & info)