From 93511da6d6a059d142978a557719ede7657c1906 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Tue, 13 Sep 2016 17:45:50 +0300 Subject: [PATCH 1/5] Adding minmax_element to algorithm.hpp --- std/algorithm.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/std/algorithm.hpp b/std/algorithm.hpp index 79b2d51384..8ad592f5d8 100644 --- a/std/algorithm.hpp +++ b/std/algorithm.hpp @@ -25,6 +25,7 @@ using std::max; using std::max_element; using std::min; using std::min_element; +using std::minmax_element; using std::next_permutation; using std::none_of; using std::nth_element; From 7a3d5a810dae814d2b8b9dfce9379eb02bb659c7 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Tue, 13 Sep 2016 17:47:05 +0300 Subject: [PATCH 2/5] Returning min and max route altitude and units. --- map/framework.cpp | 31 ++++++++++++++++++++++++++++--- map/framework.hpp | 10 +++++++++- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/map/framework.cpp b/map/framework.cpp index 92f3bccb53..9f5e13fdad 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -2988,7 +2988,9 @@ bool Framework::OriginalFeatureHasDefaultName(FeatureID const & fid) const bool Framework::HasRouteAltitude() const { return m_routingSession.HasRouteAltitude(); } bool Framework::GenerateRouteAltitudeChart(uint32_t width, uint32_t height, - vector & imageRGBAData) const + vector & imageRGBAData, + int32_t & minRouteAltitude, int32_t & maxRouteAltitude, + measurement_utils::Units & altitudeUnits) const { feature::TAltitudes altitudes; vector segDistance; @@ -2997,6 +2999,29 @@ bool Framework::GenerateRouteAltitudeChart(uint32_t width, uint32_t height, return false; segDistance.insert(segDistance.begin(), 0.0); - return maps::GenerateChart(width, height, segDistance, altitudes, - GetMapStyle(), imageRGBAData); + if (altitudes.empty()) + return false; + + if (!maps::GenerateChart(width, height, segDistance, altitudes, GetMapStyle(), imageRGBAData)) + return false; + + auto const minMaxIt = minmax_element(altitudes.cbegin(), altitudes.cend()); + feature::TAltitude const minRouteAltitudeM = *minMaxIt.first; + feature::TAltitude const maxRouteAltitudeM = *minMaxIt.second; + + altitudeUnits = measurement_utils::Units::Metric; + UNUSED_VALUE(settings::Get(settings::kMeasurementUnits, altitudeUnits)); + + switch (altitudeUnits) + { + case measurement_utils::Units::Imperial: + minRouteAltitude = measurement_utils::MetersToFeet(minRouteAltitudeM); + maxRouteAltitude = measurement_utils::MetersToFeet(maxRouteAltitudeM); + break; + case measurement_utils::Units::Metric: + minRouteAltitude = minRouteAltitudeM; + maxRouteAltitude = maxRouteAltitudeM; + break; + } + return true; } diff --git a/map/framework.hpp b/map/framework.hpp index 0b96e79f15..64511e7b6c 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -729,13 +729,21 @@ public: /// false otherwise. bool HasRouteAltitude() const; /// \brief Generates 4 bytes per point image (RGBA) and put the data to |imageRGBAData|. + /// \param width is width of chart shall be generated in pixels. + /// \param height is height of chart shall be generated in pixels. + /// \param imageRGBAData is bits of result image in RGBA. + /// \param minRouteAltitude is min altitude along the route in altitudeUnits. + /// \param maxRouteAltitude is max altitude along the route in altitudeUnits. + /// \param altitudeUnits is units (meters or feet) which is used to pass min and max altitudes. /// \returns If there is valid route info and the chart was generated returns true /// and false otherwise. If the method returns true it is guaranteed that the size of /// |imageRGBAData| is not zero. /// \note If HasRouteAltitude() method returns true, GenerateRouteAltitudeChart(...) /// could return false if route was deleted or rebuilt between the calls. bool GenerateRouteAltitudeChart(uint32_t width, uint32_t height, - vector & imageRGBAData) const; + vector & imageRGBAData, + int32_t & minRouteAltitude, int32_t & maxRouteAltitude, + measurement_utils::Units & altitudeUnits) const; public: /// @name Editor interface. From e640f5aec60268bd0d3481b522a548b355bc75ad Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Wed, 14 Sep 2016 09:28:04 +0300 Subject: [PATCH 3/5] iOS Build fix after changes in signature of GenerateRouteAltitudeChart(). --- iphone/Maps/Classes/Routing/MWMRouter.mm | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/iphone/Maps/Classes/Routing/MWMRouter.mm b/iphone/Maps/Classes/Routing/MWMRouter.mm index 320705f0ca..1f5e9ccb97 100644 --- a/iphone/Maps/Classes/Routing/MWMRouter.mm +++ b/iphone/Maps/Classes/Routing/MWMRouter.mm @@ -288,8 +288,14 @@ bool isMarkerPoint(MWMRoutePoint const & point) { return point.IsValid() && !poi if (!imageData) { vector imageRGBAData; - if (!GetFramework().GenerateRouteAltitudeChart(width, height, imageRGBAData)) + int32_t minRouteAltitude = 0; + int32_t maxRouteAltitude = 0; + measurement_utils::Units units = measurement_utils::Units::Metric; + if (!GetFramework().GenerateRouteAltitudeChart(width, height, imageRGBAData, + minRouteAltitude, maxRouteAltitude, units)) + { return; + } if (imageRGBAData.empty()) return; imageData = [NSData dataWithBytes:imageRGBAData.data() length:imageRGBAData.size()]; From a02a2bfb172c2655f39b866e5b298161e6b78dc7 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Wed, 14 Sep 2016 11:06:56 +0300 Subject: [PATCH 4/5] JNI layer for passing route altitude limits. --- android/jni/com/mapswithme/maps/Framework.cpp | 23 +++++++++++++++++-- .../src/com/mapswithme/maps/Framework.java | 12 ++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp index 0ce3effb88..37db6c3b21 100644 --- a/android/jni/com/mapswithme/maps/Framework.cpp +++ b/android/jni/com/mapswithme/maps/Framework.cpp @@ -895,18 +895,37 @@ Java_com_mapswithme_maps_Framework_nativeGetRouteFollowingInfo(JNIEnv * env, jcl } JNIEXPORT jintArray JNICALL -Java_com_mapswithme_maps_Framework_nativeGenerateRouteAltitudeChartBits(JNIEnv * env, jclass, jint width, jint height) +Java_com_mapswithme_maps_Framework_nativeGenerateRouteAltitudeChartBits(JNIEnv * env, jclass, jint width, jint height, jobject routeAltitudeLimits) { ::Framework * fr = frm(); ASSERT(fr, ()); vector imageRGBAData; - if (!fr->GenerateRouteAltitudeChart(width, height, imageRGBAData)) + int32_t minRouteAltitude = 0; + int32_t maxRouteAltitude = 0; + measurement_utils::Units units = measurement_utils::Units::Metric; + if (!fr->GenerateRouteAltitudeChart(width, height, imageRGBAData, minRouteAltitude, maxRouteAltitude, units)) { LOG(LWARNING, ("Can't generate route altitude image.")); return nullptr; } + // Passing route limits. + jclass const routeAltitudeLimitsClass = env->GetObjectClass(routeAltitudeLimits); + ASSERT(routeAltitudeLimitsClass, ()); + + static jfieldID const minRouteAltitudeField = env->GetFieldID(routeAltitudeLimitsClass, "minRouteAltitude", "I"); + ASSERT(minRouteAltitudeField, ()); + env->SetIntField(routeAltitudeLimits, minRouteAltitudeField, minRouteAltitude); + + static jfieldID const maxRouteAltitudeField = env->GetFieldID(routeAltitudeLimitsClass, "maxRouteAltitude", "I"); + ASSERT(maxRouteAltitudeField, ()); + env->SetIntField(routeAltitudeLimits, maxRouteAltitudeField, maxRouteAltitude); + + static jfieldID const isMetricUnitsField = env->GetFieldID(routeAltitudeLimitsClass, "isMetricUnits", "Z"); + ASSERT(isMetricUnitsField, ()); + env->SetBooleanField(routeAltitudeLimits, isMetricUnitsField, units == measurement_utils::Units::Metric); + size_t const imageRGBADataSize = imageRGBAData.size(); ASSERT_NOT_EQUAL(imageRGBADataSize, 0, ("GenerateRouteAltitudeChart returns true but the vector with altitude image bits is empty.")); diff --git a/android/src/com/mapswithme/maps/Framework.java b/android/src/com/mapswithme/maps/Framework.java index 2cb6e01f9d..77c4f028fe 100644 --- a/android/src/com/mapswithme/maps/Framework.java +++ b/android/src/com/mapswithme/maps/Framework.java @@ -61,6 +61,13 @@ public class Framework public boolean buildings; } + public static class RouteAltitudeLimits + { + public int minRouteAltitude; + public int maxRouteAltitude; + public boolean isMetricUnits; + } + // this class is just bridge between Java and C++ worlds, we must not create it private Framework() {} @@ -81,7 +88,8 @@ public class Framework if (width <= 0 || height <= 0) return null; - final int[] altitudeChartBits = Framework.nativeGenerateRouteAltitudeChartBits(width, height); + RouteAltitudeLimits routeAltitudeLimits = new RouteAltitudeLimits(); + final int[] altitudeChartBits = Framework.nativeGenerateRouteAltitudeChartBits(width, height, routeAltitudeLimits); if (altitudeChartBits == null) return null; @@ -165,7 +173,7 @@ public class Framework public static native RoutingInfo nativeGetRouteFollowingInfo(); @Nullable - public static native final int[] nativeGenerateRouteAltitudeChartBits(int width, int height); + public static native final int[] nativeGenerateRouteAltitudeChartBits(int width, int height, RouteAltitudeLimits routeAltitudeLimits); // When an end user is going to a turn he gets sound turn instructions. // If C++ part wants the client to pronounce an instruction nativeGenerateTurnNotifications returns From 8b0e785c52ba1cfafb1a3e0f8a3a16f6e3758186 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Wed, 14 Sep 2016 17:33:38 +0300 Subject: [PATCH 5/5] Review fixes. --- map/framework.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/map/framework.cpp b/map/framework.cpp index 9f5e13fdad..85aedd6352 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -3009,8 +3009,8 @@ bool Framework::GenerateRouteAltitudeChart(uint32_t width, uint32_t height, feature::TAltitude const minRouteAltitudeM = *minMaxIt.first; feature::TAltitude const maxRouteAltitudeM = *minMaxIt.second; - altitudeUnits = measurement_utils::Units::Metric; - UNUSED_VALUE(settings::Get(settings::kMeasurementUnits, altitudeUnits)); + if (!settings::Get(settings::kMeasurementUnits, altitudeUnits)) + altitudeUnits = measurement_utils::Units::Metric; switch (altitudeUnits) {