Welcome to mirror list, hosted at ThFree Co, Russian Federation.

route.hpp « routing - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: c3e7703e62e68545bef5ce5740571b1f19d4dae4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
#pragma once

#include "routing/road_graph.hpp"
#include "routing/routing_settings.hpp"
#include "routing/segment.hpp"
#include "routing/transit_info.hpp"
#include "routing/turns.hpp"

#include "routing/base/followed_polyline.hpp"

#include "traffic/speed_groups.hpp"

#include "indexer/feature_altitude.hpp"

#include "geometry/polyline2d.hpp"

#include "base/assert.hpp"

#include <limits>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

namespace location
{
  class GpsInfo;
  class RouteMatchingInfo;
}

namespace routing
{
using SubrouteUid = uint64_t;
SubrouteUid constexpr kInvalidSubrouteId = std::numeric_limits<uint64_t>::max();

/// \brief The route is composed of one or several subroutes. Every subroute is composed of segments.
/// For every Segment is kept some attributes in the structure SegmentInfo.
class RouteSegment final
{
public:
  RouteSegment(Segment const & segment, turns::TurnItem const & turn, Junction const & junction,
               std::string const & street, double distFromBeginningMeters,
               double distFromBeginningMerc, double timeFromBeginningS, traffic::SpeedGroup traffic,
               std::unique_ptr<TransitInfo> transitInfo)
    : m_segment(segment)
    , m_turn(turn)
    , m_junction(junction)
    , m_street(street)
    , m_distFromBeginningMeters(distFromBeginningMeters)
    , m_distFromBeginningMerc(distFromBeginningMerc)
    , m_timeFromBeginningS(timeFromBeginningS)
    , m_traffic(traffic)
    , m_transitInfo(move(transitInfo))
  {
  }

  void SetTransitInfo(std::unique_ptr<TransitInfo> transitInfo)
  {
    m_transitInfo.Set(move(transitInfo));
  }

  Segment const & GetSegment() const { return m_segment; }
  turns::TurnItem const & GetTurn() const { return m_turn; }
  Junction const & GetJunction() const { return m_junction; }
  std::string const & GetStreet() const { return m_street; }
  double GetDistFromBeginningMeters() const { return m_distFromBeginningMeters; }
  double GetDistFromBeginningMerc() const { return m_distFromBeginningMerc; }
  double GetTimeFromBeginningSec() const { return m_timeFromBeginningS; }
  traffic::SpeedGroup GetTraffic() const { return m_traffic; }

  bool HasTransitInfo() const { return m_transitInfo.HasTransitInfo(); }
  TransitInfo const & GetTransitInfo() const { return m_transitInfo.Get(); }

private:
  Segment m_segment;
  /// Turn (maneuver) information for the turn next to the |m_segment| if any.
  /// If not |m_turn::m_turn| is equal to TurnDirection::NoTurn.
  turns::TurnItem m_turn;
  /// The furthest point of the segment from the beginning of the route along the route.
  Junction m_junction;
  /// Street name of |m_segment| if any. Otherwise |m_street| is empty.
  std::string m_street;
  /// Distance from the route (not the subroute) beginning to the farthest end of |m_segment| in meters.
  double m_distFromBeginningMeters = 0.0;
  /// Distance from the route (not the subroute) beginning to the farthest end of |m_segment| in mercator.
  double m_distFromBeginningMerc = 0.0;
  /// ETA from the route beginning (not the subroute) in seconds to reach the farthest from the route beginning
  /// end of |m_segment|.
  double m_timeFromBeginningS = 0.0;
  traffic::SpeedGroup m_traffic = traffic::SpeedGroup::Unknown;
  /// Information needed to display transit segments properly.
  TransitInfoWrapper m_transitInfo;
};

class Route
{
public:
  using TTurns = std::vector<turns::TurnItem>;
  using TTimeItem = std::pair<uint32_t, double>;
  using TTimes = std::vector<TTimeItem>;
  using TStreetItem = std::pair<uint32_t, std::string>;
  using TStreets = std::vector<TStreetItem>;

  class SubrouteAttrs final
  {
  public:
    SubrouteAttrs() = default;

    SubrouteAttrs(Junction const & start, Junction const & finish, size_t beginSegmentIdx,
                  size_t endSegmentIdx)
      : m_start(start)
      , m_finish(finish)
      , m_beginSegmentIdx(beginSegmentIdx)
      , m_endSegmentIdx(endSegmentIdx)
    {
      CHECK_LESS_OR_EQUAL(beginSegmentIdx, endSegmentIdx, ());
    }

    SubrouteAttrs(SubrouteAttrs const & subroute, size_t beginSegmentIdx)
      : m_start(subroute.m_start)
      , m_finish(subroute.m_finish)
      , m_beginSegmentIdx(beginSegmentIdx)
      , m_endSegmentIdx(beginSegmentIdx + subroute.GetSize())
    {
    }

    Junction const & GetStart() const { return m_start; }
    Junction const & GetFinish() const { return m_finish; }
    size_t GetBeginSegmentIdx() const { return m_beginSegmentIdx; }
    size_t GetEndSegmentIdx() const { return m_endSegmentIdx; }
    size_t GetSize() const { return m_endSegmentIdx - m_beginSegmentIdx; }

  private:
    Junction m_start;
    Junction m_finish;
    // Index of the first subroute segment in the whole route.
    size_t m_beginSegmentIdx = 0;
    // Non inclusive index of the last subroute segment in the whole route.
    size_t m_endSegmentIdx = 0;
  };

  /// \brief For every subroute some attributes are kept the following stucture.
  struct SubrouteSettings final
  {
    SubrouteSettings(RoutingSettings const & routingSettings, std::string const & router,
                     SubrouteUid id)
      : m_routingSettings(routingSettings), m_router(router), m_id(id)
    {
    }

    RoutingSettings const m_routingSettings;
    std::string const m_router;
    /// Some subsystems (for example drape) which is used Route class need to have an id of any subroute.
    /// This subsystems may set the id and then use it. The id is kept in |m_id|.
    SubrouteUid const m_id = kInvalidSubrouteId;
  };

  explicit Route(std::string const & router)
    : m_router(router), m_routingSettings(GetRoutingSettings(VehicleType::Car)) {}

  template <class TIter>
  Route(std::string const & router, TIter beg, TIter end)
    : m_router(router), m_routingSettings(GetRoutingSettings(VehicleType::Car)), m_poly(beg, end)
  {
  }

  Route(std::string const & router, std::vector<m2::PointD> const & points,
        std::string const & name = std::string());

  void Swap(Route & rhs);

  template <class TIter> void SetGeometry(TIter beg, TIter end)
  {
    if (beg == end)
    {
      FollowedPolyline().Swap(m_poly);
    }
    else
    {
      FollowedPolyline(beg, end).Swap(m_poly);
      // If there are no intermediate points it's acceptable to have an empty m_subrouteAttrs.
      // Constructed m_poly will have the last point index as next checkpoint index, it's right.
      if (!m_subrouteAttrs.empty())
      {
        ASSERT_GREATER(m_subrouteAttrs.size(), m_currentSubrouteIdx, ());
        m_poly.SetNextCheckpointIndex(m_subrouteAttrs[m_currentSubrouteIdx].GetEndSegmentIdx());
      }
    }
  }

  template <class SI>
  void SetRouteSegments(SI && v)
  {
    m_routeSegments = std::forward<SI>(v);

    m_haveAltitudes = true;
    for (auto const & s : m_routeSegments)
    {
      if (s.GetJunction().GetAltitude() == feature::kInvalidAltitude)
      {
        m_haveAltitudes = false;
        return;
      }
    }
  }

  std::vector<RouteSegment> & GetRouteSegments() { return m_routeSegments; }

  void SetCurrentSubrouteIdx(size_t currentSubrouteIdx) { m_currentSubrouteIdx = currentSubrouteIdx; }

  template <class V>
  void SetSubroteAttrs(V && subroutes)
  {
    m_subrouteAttrs = std::forward<V>(subroutes);
    ASSERT_GREATER(m_subrouteAttrs.size(), m_currentSubrouteIdx, ());
    m_poly.SetNextCheckpointIndex(m_subrouteAttrs[m_currentSubrouteIdx].GetEndSegmentIdx());
  }

  void PassNextSubroute()
  {
    ASSERT_GREATER(m_subrouteAttrs.size(), m_currentSubrouteIdx, ());
    m_currentSubrouteIdx = std::min(m_currentSubrouteIdx + 1, m_subrouteAttrs.size() - 1);
    m_poly.SetNextCheckpointIndex(m_subrouteAttrs[m_currentSubrouteIdx].GetEndSegmentIdx());
  }

  /// \returns estimated time for the whole route.
  double GetTotalTimeSec() const;
  /// \returns estimated time to reach the route end.
  double GetCurrentTimeToEndSec() const;

  FollowedPolyline const & GetFollowedPolyline() const { return m_poly; }

  std::string const & GetRouterId() const { return m_router; }
  m2::PolylineD const & GetPoly() const { return m_poly.GetPolyline(); }
  
  size_t GetCurrentSubrouteIdx() const { return m_currentSubrouteIdx; }
  std::vector<SubrouteAttrs> const & GetSubroutes() const { return m_subrouteAttrs; }

  std::vector<double> const & GetSegDistanceMeters() const { return m_poly.GetSegDistanceMeters(); }
  bool IsValid() const { return (m_poly.GetPolyline().GetSize() > 1); }

  double GetTotalDistanceMeters() const;
  double GetCurrentDistanceFromBeginMeters() const;
  double GetCurrentDistanceToEndMeters() const;
  double GetMercatorDistanceFromBegin() const;

  /// \brief GetCurrentTurn returns information about the nearest turn.
  /// \param distanceToTurnMeters is a distance from current position to the nearest turn.
  /// \param turn is information about the nearest turn.
  void GetCurrentTurn(double & distanceToTurnMeters, turns::TurnItem & turn) const;

  /// \brief Returns a name of a street where the user rides at this moment.
  void GetCurrentStreetName(std::string & name) const;

  /// \brief Returns a name of a street next to idx point of the path. Function avoids short unnamed links.
  void GetStreetNameAfterIdx(uint32_t idx, std::string & name) const;

  /// \brief Gets turn information after the turn next to the nearest one.
  /// \param distanceToTurnMeters is a distance from current position to the second turn.
  /// \param nextTurn is information about the second turn.
  /// \note All parameters are filled while a GetNextTurn function call.
  bool GetNextTurn(double & distanceToTurnMeters, turns::TurnItem & nextTurn) const;
  /// \brief Extract information about zero, one or two nearest turns depending on current position.
  bool GetNextTurns(std::vector<turns::TurnItemDist> & turns) const;

  void GetCurrentDirectionPoint(m2::PointD & pt) const;

  /// @return true  If position was updated successfully (projection within gps error radius).
  bool MoveIterator(location::GpsInfo const & info);

  void MatchLocationToRoute(location::GpsInfo & location, location::RouteMatchingInfo & routeMatchingInfo) const;

  /// Add country name if we have no country filename to make route
  void AddAbsentCountry(std::string const & name);

  /// Get absent file list of a routing files for shortest path finding
  std::set<std::string> const & GetAbsentCountries() const { return m_absentCountries; }

  inline void SetRoutingSettings(RoutingSettings const & routingSettings)
  {
    m_routingSettings = routingSettings;
  }

  // Subroute interface.
  /// \returns Number of subroutes.
  /// \note Intermediate points separate a route into several subroutes.
  size_t GetSubrouteCount() const;

  /// \brief Fills |info| with full subroute information.
  /// \param subrouteIdx zero base number of subroute. |segmentIdx| should be less than GetSubrouteCount();
  /// \note |info| is a segment oriented route. Size of |info| is equal to number of points in |m_poly| - 1.
  /// Class Route is a point oriented route. While this conversion some attributes of zero point will be lost.
  /// It happens with zero turn for example.
  /// \note It's a fake implementation for single subroute which is equal to route without any
  /// intermediate points.
  /// Note. SegmentInfo::m_segment is filled with default Segment instance.
  /// Note. SegmentInfo::m_streetName is filled with an empty string.
  void GetSubrouteInfo(size_t subrouteIdx, std::vector<RouteSegment> & segments) const;

  SubrouteAttrs const & GetSubrouteAttrs(size_t subrouteIdx) const;

  /// \returns Subroute settings by |segmentIdx|.
  // @TODO(bykoianko) This method should return SubrouteSettings by reference. Now it returns by value
  // because of fake implementation.
  SubrouteSettings const GetSubrouteSettings(size_t segmentIdx) const;

  bool IsSubroutePassed(size_t subrouteIdx) const;

  /// \brief Sets subroute unique id (|subrouteUid|) by |segmentIdx|.
  /// \note |subrouteUid| is a permanent id of a subroute. This id can be used to address to a subroute
  /// after the route is removed.
  void SetSubrouteUid(size_t segmentIdx, SubrouteUid subrouteUid);

  void GetAltitudes(feature::TAltitudes & altitudes) const;
  bool HaveAltitudes() const { return m_haveAltitudes; }
  traffic::SpeedGroup GetTraffic(size_t segmentIdx) const;

  void GetTurnsForTesting(std::vector<turns::TurnItem> & turns) const;

private:
  friend std::string DebugPrint(Route const & r);

  double GetPolySegAngle(size_t ind) const;
  void GetClosestTurn(size_t segIdx, turns::TurnItem & turn) const;
  size_t ConvertPointIdxToSegmentIdx(size_t pointIdx) const;

  /// \returns Estimated time to pass the route segment with |segIdx|.
  double GetTimeToPassSegSec(size_t segIdx) const;
  /// \returns Length of the route segment with |segIdx| in meters.
  double GetSegLenMeters(size_t segIdx) const;
  /// \returns ETA to the last passed route point in seconds.
  double GetETAToLastPassedPointSec() const;

  std::string m_router;
  RoutingSettings m_routingSettings;
  std::string m_name;

  FollowedPolyline m_poly;

  std::set<std::string> m_absentCountries;
  std::vector<RouteSegment> m_routeSegments;
  // |m_haveAltitudes| is true if and only if all route points have altitude information.
  bool m_haveAltitudes = false;

  // Subroute
  SubrouteUid m_subrouteUid = kInvalidSubrouteId;
  size_t m_currentSubrouteIdx = 0;
  std::vector<SubrouteAttrs> m_subrouteAttrs;
};
} // namespace routing