! * \brief Calculates |nextIndex| which is an index of next route point at result.GetSegments() * in forward direction. * If * - |index| points at the last point of the turn segment: * - and the route at this point leads from one big road to another one * - and the other possible turns lead to small roads or there's no them * - and the turn is GoStraight or TurnSlight* * method return
| 132 | * \returns true if |nextIndex| fills correctly and false otherwise. |
| 133 | */ |
| 134 | bool GetNextCrossSegmentRoutePoint(IRoutingResult const & result, RoutePointIndex const & index, |
| 135 | NumMwmIds const & numMwmIds, RoutePointIndex & nextIndex) |
| 136 | { |
| 137 | auto const & segments = result.GetSegments(); |
| 138 | ASSERT_LESS(index.m_segmentIndex, segments.size(), ()); |
| 139 | ASSERT_LESS(index.m_pathIndex, segments[index.m_segmentIndex].m_path.size(), ()); |
| 140 | |
| 141 | if (index.m_pathIndex + 1 != segments[index.m_segmentIndex].m_path.size()) |
| 142 | { |
| 143 | // In segment case. |
| 144 | nextIndex = {index.m_segmentIndex, index.m_pathIndex + 1}; |
| 145 | return true; |
| 146 | } |
| 147 | |
| 148 | // Case when the last point of the current segment is reached. |
| 149 | // So probably it's necessary to cross a segment border. |
| 150 | if (index.m_segmentIndex + 1 == segments.size()) |
| 151 | return false; // The end of the route is reached. |
| 152 | |
| 153 | TurnInfo const turnInfo(&segments[index.m_segmentIndex], &segments[index.m_segmentIndex + 1]); |
| 154 | |
| 155 | double const oneSegmentTurnAngle = CalcOneSegmentTurnAngle(turnInfo); |
| 156 | CarDirection const oneSegmentDirection = IntermediateDirection(oneSegmentTurnAngle); |
| 157 | if (!IsGoStraightOrSlightTurn(oneSegmentDirection)) |
| 158 | return false; // Too sharp turn angle. |
| 159 | |
| 160 | size_t ingoingCount = 0; |
| 161 | TurnCandidates possibleTurns; |
| 162 | result.GetPossibleTurns(turnInfo.m_ingoing->m_segmentRange, GetPointByIndex(segments, index), ingoingCount, |
| 163 | possibleTurns); |
| 164 | |
| 165 | if (possibleTurns.candidates.empty()) |
| 166 | return false; |
| 167 | |
| 168 | // |segments| is a vector of |LoadedPathSegment|. Every |LoadedPathSegment::m_path| |
| 169 | // contains junctions of the segment. The first junction at a |LoadedPathSegment::m_path| |
| 170 | // is the same (or almost the same) with the last junction at the next |LoadedPathSegment::m_path|. |
| 171 | // To prevent using the same point twice it's necessary to take the first point only from the |
| 172 | // first item of |loadedSegments|. The beginning should be ignored for the rest |m_path|. |
| 173 | // Please see a comment in MakeTurnAnnotation() for more details. |
| 174 | if (possibleTurns.candidates.size() == 1) |
| 175 | { |
| 176 | // Taking the next point of the next segment. |
| 177 | nextIndex = {index.m_segmentIndex + 1, 1 /* m_pathIndex */}; |
| 178 | return true; |
| 179 | } |
| 180 | |
| 181 | if (CanDiscardTurnByHighwayClass(possibleTurns.candidates, turnInfo, numMwmIds)) |
| 182 | { |
| 183 | // Taking the next point of the next segment. |
| 184 | nextIndex = {index.m_segmentIndex + 1, 1 /* m_pathIndex */}; |
| 185 | return true; |
| 186 | } |
| 187 | // Stopping getting next route points because an important bifurcation point is reached. |
| 188 | return false; |
| 189 | } |
| 190 | |
| 191 | bool GetPrevInSegmentRoutePoint(IRoutingResult const & result, RoutePointIndex const & index, |
no test coverage detected