From 3e66bede21f8a6755897f65c95bc91b0066a4c14 Mon Sep 17 00:00:00 2001 From: Vladimir Byko-Ianko Date: Wed, 31 Aug 2016 17:33:23 +0300 Subject: [PATCH] Generating route altitude chart image. --- map/framework.cpp | 29 ++++ map/framework.hpp | 4 + map/generate_chart.cpp | 212 +++++++++++++++++++++++++ map/generate_chart.hpp | 37 +++++ map/map.pro | 2 + map/map_tests/generate_chart_tests.cpp | 0 routing/base/followed_polyline.hpp | 1 + routing/osrm_router.cpp | 12 +- routing/road_graph_router.cpp | 13 +- routing/route.cpp | 1 + routing/route.hpp | 23 ++- routing/routing_session.cpp | 29 ++++ routing/routing_session.hpp | 12 ++ routing/routing_tests/route_tests.cpp | 10 +- 14 files changed, 365 insertions(+), 20 deletions(-) create mode 100644 map/generate_chart.cpp create mode 100644 map/generate_chart.hpp create mode 100644 map/map_tests/generate_chart_tests.cpp diff --git a/map/framework.cpp b/map/framework.cpp index fef2c26140..6f41ecb918 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1,5 +1,6 @@ #include "map/framework.hpp" #include "map/ge0_parser.hpp" +#include "map/generate_chart.hpp" #include "map/geourl_process.hpp" #include "map/gps_tracker.hpp" #include "map/user_mark.hpp" @@ -79,6 +80,7 @@ #include "std/algorithm.hpp" #include "std/bind.hpp" +#include "std/deque.hpp" #include "std/target_os.hpp" #include "std/vector.hpp" @@ -2981,3 +2983,30 @@ bool Framework::OriginalFeatureHasDefaultName(FeatureID const & fid) const { return osm::Editor::Instance().OriginalFeatureHasDefaultName(fid); } + +bool Framework::HasRouteAltitude() const +{ + return m_routingSession.HasRouteAltitude(); +} + +bool Framework::GenerateRouteAltitudeChart(size_t width, size_t height, bool day, + vector & imageRGBAData) const +{ + feature::TAltitudes altitudes; + if (!m_routingSession.GetRouteAltitudes(altitudes) && altitudes.empty()) + return false; + deque segDistanceM; + if (!m_routingSession.GetSegDistanceM(segDistanceM) && segDistanceM.empty()) + return false; + segDistanceM.push_front(0.0); + + if (altitudes.size() != segDistanceM.size()) + { + LOG(LERROR, ("The route is in inconsistent state. Size of altitudes is", altitudes.size(), + ". Number of segment is", segDistanceM.size())); + } + + // @TODO It's necessary to normalize and center altitude information. + GenerateChart(width, height, segDistanceM, altitudes, day, imageRGBAData); + return true; +} diff --git a/map/framework.hpp b/map/framework.hpp index 98774d76f3..b96e06b3b1 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -725,6 +725,10 @@ public: void AllowAutoZoom(bool allowAutoZoom); void SaveAutoZoom(bool allowAutoZoom); + bool HasRouteAltitude() const; + bool GenerateRouteAltitudeChart(size_t width, size_t height, bool day, + vector & imageRGBAData) const; + public: /// @name Editor interface. //@{ diff --git a/map/generate_chart.cpp b/map/generate_chart.cpp new file mode 100644 index 0000000000..9218fee131 --- /dev/null +++ b/map/generate_chart.cpp @@ -0,0 +1,212 @@ +#include "map/generate_chart.hpp" + +#include "base/assert.hpp" + +#include "std/algorithm.hpp" +#include "std/fstream.hpp" + +#include "3party/agg/agg_conv_curve.h" +#include "3party/agg/agg_conv_stroke.h" +#include "3party/agg/agg_path_storage.h" +#include "3party/agg/agg_pixfmt_rgba.h" +#include "3party/agg/agg_rasterizer_scanline_aa.h" +#include "3party/agg/agg_renderer_primitives.h" +#include "3party/agg/agg_renderer_scanline.h" +#include "3party/agg/agg_scanline_p.h" + +namespace +{ +template +struct BlendAdaptor +{ + using order_type = Order; + using color_type = Color; + using TValueType = typename color_type::value_type; + using TCalcType = typename color_type::calc_type; + + enum + { + ScaleShift = color_type::base_shift, + ScaleMask = color_type::base_mask, + }; + + static AGG_INLINE void blend_pix(unsigned op, TValueType * p, unsigned cr, unsigned cg, + unsigned cb, unsigned ca, unsigned cover) + { + using TBlendTable = agg::comp_op_table_rgba; + if (p[Order::A]) + { + TBlendTable::g_comp_op_func[op](p, (cr * ca + ScaleMask) >> ScaleShift, (cg * ca + ScaleMask) >> ScaleShift, + (cb * ca + ScaleMask) >> ScaleShift, ca, cover); + } + else + { + TBlendTable::g_comp_op_func[op](p, cr, cg, cb, ca, cover); + } + } +}; +} // namespace + +void NormalizeChartData(deque const & distanceDataM, feature::TAltitudes const & altitudeDataM, + size_t resultPointCount, vector & uniformAltitudeDataM) +{ + uniformAltitudeDataM.clear(); + if (distanceDataM.empty() || resultPointCount == 0 || distanceDataM.size() != altitudeDataM.size()) + return; + + if (!is_sorted(distanceDataM.cbegin(), distanceDataM.cend())) + { + LOG(LERROR, ("Route segment distances are not sorted.")); + return; + } + + uniformAltitudeDataM.resize(resultPointCount); + double const routeLenM = distanceDataM.back(); + double const stepLenM = routeLenM / static_cast (resultPointCount - 1); + + auto const calculateAltitude = [&](double distFormStartM) + { + if (distFormStartM <= distanceDataM.front() ) + return static_cast(altitudeDataM.front()); + if (distFormStartM >= distanceDataM.back()) + return static_cast(altitudeDataM.back()); + + auto const lowerIt = lower_bound(distanceDataM.cbegin(), distanceDataM.cend(), distFormStartM); + if (lowerIt == distanceDataM.cbegin()) + return static_cast(altitudeDataM.front()); + if (lowerIt == distanceDataM.cend()) + return static_cast(altitudeDataM.back()); + + size_t const nextPointIdx = distance(distanceDataM.cbegin(), lowerIt); + CHECK_LESS(0, nextPointIdx, ()); + size_t const prevPointIdx = nextPointIdx - 1; + + if (distanceDataM[prevPointIdx] == distanceDataM[nextPointIdx]) + return static_cast(altitudeDataM[prevPointIdx]); + + double const k = (altitudeDataM[nextPointIdx] - altitudeDataM[prevPointIdx]) / + (distanceDataM[nextPointIdx] - distanceDataM[prevPointIdx]); + return static_cast(altitudeDataM[prevPointIdx]) + k * (distFormStartM - distanceDataM[prevPointIdx]); + }; + + uniformAltitudeDataM.resize(resultPointCount); + for (size_t i = 0; i < resultPointCount; ++i) + uniformAltitudeDataM[i] = calculateAltitude(static_cast(i) * stepLenM); +} + +void GenerateYAxisChartData(size_t height, double minMetersPerPxl, + vector const & altitudeDataM, vector & yAxisDataPxl) +{ + uint32_t constexpr kHeightIndentPxl = 2.0; + yAxisDataPxl.clear(); + uint32_t heightIndent = kHeightIndentPxl; + if (height <= 2 * kHeightIndentPxl) + { + LOG(LERROR, ("Chart height is less then 2 * kHeightIndentPxl (", 2 * kHeightIndentPxl, ")")); + heightIndent = 0; + } + + auto const minMaxAltitudeIt = minmax_element(altitudeDataM.begin(), altitudeDataM.end()); + double const minAltM = *minMaxAltitudeIt.first; + double const maxAltM = *minMaxAltitudeIt.second; + double const deltaAltM = maxAltM - minAltM; + uint32_t const drawHeightPxl = height - 2 * heightIndent; + double const meterPerPxl = max(minMetersPerPxl, deltaAltM / static_cast(drawHeightPxl)); + if (meterPerPxl == 0.0) + { + LOG(LERROR, ("meterPerPxl == 0.0")); + return; + } + + size_t const altitudeDataSz = altitudeDataM.size(); + yAxisDataPxl.resize(altitudeDataSz); + for (size_t i = 0; i < altitudeDataSz; ++i) + yAxisDataPxl[i] = height - heightIndent - (altitudeDataM[i] - minAltM) / meterPerPxl; +} + +void GenerateChartByPoints(size_t width, size_t height, vector const & geometry, + bool day, vector & frameBuffer) +{ + frameBuffer.clear(); + if (width == 0 || height == 0 || geometry.empty()) + return; + + agg::rgba8 const kBackgroundColor = agg::rgba8(255, 255, 255, 0); + agg::rgba8 const kLineColor = day ? agg::rgba8(30, 150, 240, 255) : agg::rgba8(255, 230, 140, 255); + agg::rgba8 const kCurveColor = day ? agg::rgba8(30, 150, 240, 20) : agg::rgba8(255, 230, 140, 20); + double constexpr kLineWidthPxl = 2.0; + uint32_t constexpr kBPP = 4; + + using TBlender = BlendAdaptor; + using TPixelFormat = agg::pixfmt_custom_blend_rgba; + using TBaseRenderer = agg::renderer_base; + using TPrimitivesRenderer = agg::renderer_primitives; + using TSolidRenderer = agg::renderer_scanline_aa_solid; + using TPath = agg::poly_container_adaptor>; + using TStroke = agg::conv_stroke; + + agg::rendering_buffer renderBuffer; + TPixelFormat pixelFormat(renderBuffer, agg::comp_op_src_over); + TBaseRenderer m_baseRenderer(pixelFormat); + + frameBuffer.assign(width * kBPP * height, 0); + renderBuffer.attach(&frameBuffer[0], static_cast(width), + static_cast(height), + static_cast(width * kBPP)); + m_baseRenderer.reset_clipping(true); + unsigned op = pixelFormat.comp_op(); + pixelFormat.comp_op(agg::comp_op_src); + m_baseRenderer.clear(kBackgroundColor); + pixelFormat.comp_op(op); + + agg::rasterizer_scanline_aa<> rasterizer; + rasterizer.clip_box(0, 0, width, height); + + // Polygon under chart line. + agg::path_storage underChartGeometryPath; + underChartGeometryPath.move_to(geometry.front().x, static_cast(height)); + for (auto const & p : geometry) + underChartGeometryPath.line_to(p.x, p.y); + underChartGeometryPath.line_to(geometry.back().x, static_cast(height)); + underChartGeometryPath.close_polygon(); + + agg::conv_curve curve(underChartGeometryPath); + rasterizer.add_path(curve); + agg::scanline32_p8 scanline; + agg::render_scanlines_aa_solid(rasterizer, scanline, m_baseRenderer, kCurveColor); + + // Chart line. + TPath path_adaptor(geometry, false); + TStroke stroke(path_adaptor); + stroke.width(kLineWidthPxl); + stroke.line_cap(agg::round_cap); + stroke.line_join(agg::round_join); + + rasterizer.add_path(stroke); + agg::render_scanlines_aa_solid(rasterizer, scanline, m_baseRenderer, kLineColor); +} + +void GenerateChart(size_t width, size_t height, + deque const & distanceDataM, feature::TAltitudes const & altitudeDataM, + bool day, vector & frameBuffer) +{ + frameBuffer.clear(); + if (altitudeDataM.empty() || distanceDataM.size() != altitudeDataM.size()) + return; + + vector uniformAltitudeDataM; + NormalizeChartData(distanceDataM, altitudeDataM, width, uniformAltitudeDataM); + if (uniformAltitudeDataM.empty()) + return; + + vector yAxisDataPxl; + GenerateYAxisChartData(height, 1.0 /* minMetersPerPxl */, uniformAltitudeDataM, yAxisDataPxl); + + size_t const uniformAltitudeDataSz = yAxisDataPxl.size(); + double const oneSegLenPix = static_cast(width) / (uniformAltitudeDataSz - 1); + vector geometry(uniformAltitudeDataSz); + for (size_t i = 0; i < uniformAltitudeDataSz; ++i) + geometry[i] = m2::PointD(i * oneSegLenPix, yAxisDataPxl[i]); + + GenerateChartByPoints(width, height, geometry, day, frameBuffer); +} diff --git a/map/generate_chart.hpp b/map/generate_chart.hpp new file mode 100644 index 0000000000..9df6d77336 --- /dev/null +++ b/map/generate_chart.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include "indexer/feature_altitude.hpp" + +#include "geometry/point2d.hpp" + +#include "std/deque.hpp" +#include "std/vector.hpp" + +/// \brief fills uniformAltitudeDataM with altitude data which evenly distributed by +/// |resultPointCount| points. |distanceDataM| and |altitudeDataM| form a curve of route altitude. +/// This method is used to generalize and evenly distribute points of the chart. +void NormalizeChartData(deque const & distanceDataM, feature::TAltitudes const & altitudeDataM, + size_t resultPointCount, vector & uniformAltitudeDataM); + +/// \brief fills |yAxisDataPxl|. |yAxisDataPxl| is formed to pevent displaying +/// big waves on the chart in case of small deviation in absolute values in |yAxisData|. +/// \param height image chart height in pixels. +/// \param minMetersInPixel minimum meter number per height pixel. +/// \param altitudeDataM altitude data vector in meters. +/// \param yAxisDataPxl Y-axis data of altitude chart in pixels. +void GenerateYAxisChartData(size_t height, double minMetersPerPxl, + vector const & altitudeDataM, vector & yAxisDataPxl); + +/// \brief generates chart image on a canvas with size |width|, |height| with |geometry|. +/// (0, 0) is a left-top corner. X-axis goes down and Y-axis goes right. +/// \param width is result image width in pixels. +/// \param height is result image height in pixels. +/// \param geometry is points which is used to draw a curve of the chart. +/// \param frameBuffer is a vector for a result image. It's resized in this method. +/// It's filled with RGBA(8888) image date. +void GenerateChartByPoints(size_t width, size_t height, vector const & geometry, + bool day, vector & frameBuffer); + +void GenerateChart(size_t width, size_t height, + deque const & distanceDataM, feature::TAltitudes const & altitudeDataM, + bool day, vector & frameBuffer); diff --git a/map/map.pro b/map/map.pro index 582f3744d1..5e0b516012 100644 --- a/map/map.pro +++ b/map/map.pro @@ -19,6 +19,7 @@ HEADERS += \ feature_vec_model.hpp \ framework.hpp \ ge0_parser.hpp \ + generate_chart.hpp \ geourl_process.hpp \ gps_track.hpp \ gps_track_collection.hpp \ @@ -42,6 +43,7 @@ SOURCES += \ feature_vec_model.cpp \ framework.cpp \ ge0_parser.cpp \ + generate_chart.cpp \ geourl_process.cpp \ gps_track.cpp \ gps_track_collection.cpp \ diff --git a/map/map_tests/generate_chart_tests.cpp b/map/map_tests/generate_chart_tests.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/routing/base/followed_polyline.hpp b/routing/base/followed_polyline.hpp index 36d700d27d..66d3fd8a85 100644 --- a/routing/base/followed_polyline.hpp +++ b/routing/base/followed_polyline.hpp @@ -23,6 +23,7 @@ public: bool IsValid() const { return (m_current.IsValid() && m_poly.GetSize() > 1); } m2::PolylineD const & GetPolyline() const { return m_poly; } + vector const & GetSegDistanceM() const { return m_segDistance; } double GetTotalDistanceM() const; double GetDistanceFromBeginM() const; diff --git a/routing/osrm_router.cpp b/routing/osrm_router.cpp index 01954a3416..4d94c0d33c 100644 --- a/routing/osrm_router.cpp +++ b/routing/osrm_router.cpp @@ -366,9 +366,9 @@ OsrmRouter::ResultCode OsrmRouter::MakeRouteFromCrossesPath(TCheckedPath const & } route.SetGeometry(points.begin(), points.end()); - route.SetTurnInstructions(turnsDir); - route.SetSectionTimes(times); - route.SetStreetNames(streets); + route.SwapTurnInstructions(turnsDir); + route.SwapSectionTimes(times); + route.SwapStreetNames(streets); return NoError; } @@ -504,9 +504,9 @@ OsrmRouter::ResultCode OsrmRouter::CalculateRoute(m2::PointD const & startPoint, } route.SetGeometry(points.begin(), points.end()); - route.SetTurnInstructions(turnsDir); - route.SetSectionTimes(times); - route.SetStreetNames(streets); + route.SwapTurnInstructions(turnsDir); + route.SwapSectionTimes(times); + route.SwapStreetNames(streets); return NoError; } diff --git a/routing/road_graph_router.cpp b/routing/road_graph_router.cpp index 8970f54d07..1b11626688 100644 --- a/routing/road_graph_router.cpp +++ b/routing/road_graph_router.cpp @@ -9,6 +9,7 @@ #include "coding/reader_wrapper.hpp" +#include "indexer/feature_altitude.hpp" #include "indexer/feature.hpp" #include "indexer/ftypes_matcher.hpp" #include "indexer/index.hpp" @@ -19,6 +20,7 @@ #include "geometry/distance.hpp" +#include "std/algorithm.hpp" #include "std/queue.hpp" #include "std/set.hpp" @@ -247,10 +249,15 @@ void RoadGraphRouter::ReconstructRoute(vector && path, Route & route, if (m_directionsEngine) m_directionsEngine->Generate(*m_roadGraph, path, times, turnsDir, geometry, cancellable); + feature::TAltitudes altitudes(path.size()); + for (size_t i = 0; i < path.size(); ++i) + altitudes[i] = path[i].GetAltitude(); + route.SetGeometry(geometry.begin(), geometry.end()); - route.SetSectionTimes(times); - route.SetTurnInstructions(turnsDir); - route.SetStreetNames(streetNames); + route.SwapSectionTimes(times); + route.SwapTurnInstructions(turnsDir); + route.SwapStreetNames(streetNames); + route.SwapAltitudes(altitudes); } unique_ptr CreatePedestrianAStarRouter(Index & index, TCountryFileFn const & countryFileFn) diff --git a/routing/route.cpp b/routing/route.cpp index da81fb98dd..27ed38b71c 100644 --- a/routing/route.cpp +++ b/routing/route.cpp @@ -41,6 +41,7 @@ void Route::Swap(Route & rhs) swap(m_times, rhs.m_times); swap(m_streets, rhs.m_streets); m_absentCountries.swap(rhs.m_absentCountries); + m_altitudes.swap(rhs.m_altitudes); } void Route::AddAbsentCountry(string const & name) diff --git a/routing/route.hpp b/routing/route.hpp index 0014f81f88..55aeab4eee 100644 --- a/routing/route.hpp +++ b/routing/route.hpp @@ -1,11 +1,14 @@ #pragma once -#include "base/followed_polyline.hpp" -#include "routing_settings.hpp" -#include "turns.hpp" +#include "routing/routing_settings.hpp" +#include "routing/turns.hpp" + +#include "indexer/feature_altitude.hpp" #include "geometry/polyline2d.hpp" +#include "base/followed_polyline.hpp" + #include "std/vector.hpp" #include "std/set.hpp" #include "std/string.hpp" @@ -52,21 +55,26 @@ public: Update(); } - inline void SetTurnInstructions(TTurns & v) + inline void SwapTurnInstructions(TTurns & v) { swap(m_turns, v); } - inline void SetSectionTimes(TTimes & v) + inline void SwapSectionTimes(TTimes & v) { swap(m_times, v); } - inline void SetStreetNames(TStreets & v) + inline void SwapStreetNames(TStreets & v) { swap(m_streets, v); } + inline void SwapAltitudes(feature::TAltitudes & v) + { + swap(m_altitudes, v); + } + uint32_t GetTotalTimeSec() const; uint32_t GetCurrentTimeToEndSec() const; @@ -75,6 +83,8 @@ public: string const & GetRouterId() const { return m_router; } m2::PolylineD const & GetPoly() const { return m_poly.GetPolyline(); } TTurns const & GetTurns() const { return m_turns; } + feature::TAltitudes const & GetAltitudes() const { return m_altitudes; } + vector const & GetSegDistanceM() const { return m_poly.GetSegDistanceM(); } void GetTurnsDistances(vector & distances) const; string const & GetName() const { return m_name; } bool IsValid() const { return (m_poly.GetPolyline().GetSize() > 1); } @@ -148,6 +158,7 @@ private: TTurns m_turns; TTimes m_times; TStreets m_streets; + feature::TAltitudes m_altitudes; mutable double m_currentTime; }; diff --git a/routing/routing_session.cpp b/routing/routing_session.cpp index 0de247706d..bc57f7f772 100644 --- a/routing/routing_session.cpp +++ b/routing/routing_session.cpp @@ -523,6 +523,35 @@ void RoutingSession::EmitCloseRoutingEvent() const alohalytics::Location::FromLatLon(lastGoodPoint.lat, lastGoodPoint.lon)); } +bool RoutingSession::HasRouteAltitudeImpl() const +{ + return !m_route.GetAltitudes().empty(); +} + +bool RoutingSession::HasRouteAltitude() const +{ + threads::MutexGuard guard(m_routeSessionMutex); + return HasRouteAltitudeImpl(); +} + +bool RoutingSession::GetRouteAltitudes(feature::TAltitudes & routeAltitudes) const +{ + threads::MutexGuard guard(m_routeSessionMutex); + if (!HasRouteAltitudeImpl()) + return false; + routeAltitudes.assign(m_route.GetAltitudes().begin(), m_route.GetAltitudes().end()); + return true; +} + +bool RoutingSession::GetSegDistanceM(deque & routeSegDistanceM) const +{ + threads::MutexGuard guard(m_routeSessionMutex); + if (!m_route.IsValid()) + return false; + routeSegDistanceM.assign(m_route.GetSegDistanceM().begin(), m_route.GetSegDistanceM().end()); + return true; +} + string DebugPrint(RoutingSession::State state) { switch (state) diff --git a/routing/routing_session.hpp b/routing/routing_session.hpp index 478d4c9f98..b92fa320df 100644 --- a/routing/routing_session.hpp +++ b/routing/routing_session.hpp @@ -15,6 +15,7 @@ #include "base/mutex.hpp" #include "std/atomic.hpp" +#include "std/deque.hpp" #include "std/limits.hpp" #include "std/unique_ptr.hpp" @@ -105,6 +106,15 @@ public: inline void SetState(State state) { m_state = state; } Route const & GetRoute() const { return m_route; } + /// \returns true if any altitude information along |m_route| is available and + /// false otherwise. + bool HasRouteAltitude() const; + /// \brief copies route altitude information to |routeAltitudes| if any is available and + /// returns true. If no route altitude information is available returns false. + bool GetRouteAltitudes(feature::TAltitudes & routeAltitudes) const; + /// \brief copies distance from route beginning to ends of route segments in meters and + /// returns true. If the route is not valid returns false. + bool GetSegDistanceM(deque & routeSegDistanceM) const; State OnLocationPositionChanged(location::GpsInfo const & info, Index const & index); void GetRouteFollowingInfo(location::FollowingInfo & info) const; @@ -165,6 +175,8 @@ private: void RemoveRoute(); void RemoveRouteImpl(); + bool HasRouteAltitudeImpl() const; + private: unique_ptr m_router; Route m_route; diff --git a/routing/routing_tests/route_tests.cpp b/routing/routing_tests/route_tests.cpp index bbb2c7a06f..821e4a59ac 100644 --- a/routing/routing_tests/route_tests.cpp +++ b/routing/routing_tests/route_tests.cpp @@ -50,7 +50,7 @@ UNIT_TEST(DistanceToCurrentTurnTest) Route route("TestRouter"); route.SetGeometry(kTestGeometry.begin(), kTestGeometry.end()); vector turns(kTestTurns); - route.SetTurnInstructions(turns); + route.SwapTurnInstructions(turns); double distance; turns::TurnItem turn; @@ -85,7 +85,7 @@ UNIT_TEST(NextTurnTest) Route route("TestRouter"); route.SetGeometry(kTestGeometry.begin(), kTestGeometry.end()); vector turns(kTestTurns); - route.SetTurnInstructions(turns); + route.SwapTurnInstructions(turns); double distance, nextDistance; turns::TurnItem turn; @@ -114,7 +114,7 @@ UNIT_TEST(NextTurnsTest) Route route("TestRouter"); route.SetGeometry(kTestGeometry.begin(), kTestGeometry.end()); vector turns(kTestTurns); - route.SetTurnInstructions(turns); + route.SwapTurnInstructions(turns); vector turnsDist; { @@ -165,9 +165,9 @@ UNIT_TEST(RouteNameTest) route.SetGeometry(kTestGeometry.begin(), kTestGeometry.end()); vector turns(kTestTurns); - route.SetTurnInstructions(turns); + route.SwapTurnInstructions(turns); Route::TStreets names(kTestNames); - route.SetStreetNames(names); + route.SwapStreetNames(names); string name; route.GetCurrentStreetName(name);