| 211 | } |
| 212 | |
| 213 | bool ScorePathsConnector::FindShortestPath(Graph::Edge const & from, Graph::Edge const & to, LinearSegmentSource source, |
| 214 | FunctionalRoadClass lowestFrcToNextPoint, uint32_t maxPathLength, |
| 215 | Graph::EdgeVector & path) |
| 216 | { |
| 217 | double constexpr kLengthToleranceFactor = 1.1; |
| 218 | uint32_t constexpr kMinLengthTolerance = 20; |
| 219 | uint32_t const lengthToleranceM = |
| 220 | max(static_cast<uint32_t>(kLengthToleranceFactor * maxPathLength), kMinLengthTolerance); |
| 221 | |
| 222 | struct State |
| 223 | { |
| 224 | State(Graph::Edge const & e, uint32_t const s) : m_edge(e), m_score(s) {} |
| 225 | |
| 226 | bool operator>(State const & o) const { return tie(m_score, m_edge) > tie(o.m_score, o.m_edge); } |
| 227 | |
| 228 | Graph::Edge m_edge; |
| 229 | uint32_t m_score; |
| 230 | }; |
| 231 | |
| 232 | CHECK(from.HasRealPart() && to.HasRealPart(), ()); |
| 233 | |
| 234 | priority_queue<State, vector<State>, greater<>> q; |
| 235 | map<Graph::Edge, double> scores; |
| 236 | map<Graph::Edge, Graph::Edge> links; |
| 237 | |
| 238 | q.emplace(from, 0); |
| 239 | scores[from] = 0; |
| 240 | |
| 241 | while (!q.empty()) |
| 242 | { |
| 243 | auto const state = q.top(); |
| 244 | q.pop(); |
| 245 | |
| 246 | auto const & stateEdge = state.m_edge; |
| 247 | // TODO(mgsergio): Unify names: use either score or distance. |
| 248 | auto const stateScore = state.m_score; |
| 249 | |
| 250 | if (stateScore > maxPathLength + lengthToleranceM) |
| 251 | continue; |
| 252 | |
| 253 | if (stateScore > scores[stateEdge]) |
| 254 | continue; |
| 255 | |
| 256 | if (AreEdgesEqualWithoutAltitude(stateEdge, to)) |
| 257 | { |
| 258 | for (auto edge = stateEdge; edge != from; edge = links[edge]) |
| 259 | path.emplace_back(edge); |
| 260 | path.emplace_back(from); |
| 261 | reverse(begin(path), end(path)); |
| 262 | return true; |
| 263 | } |
| 264 | |
| 265 | Graph::EdgeListT edges; |
| 266 | m_graph.GetOutgoingEdges(stateEdge.GetEndJunction(), edges); |
| 267 | for (auto const & edge : edges) |
| 268 | { |
| 269 | if (source == LinearSegmentSource::FromLocationReferenceTag && |
| 270 | !ConformLfrcnpV3(edge, lowestFrcToNextPoint, m_infoGetter)) |
nothing calls this directly
no test coverage detected