void GetMoves(LevenshteinDFA::Position const & p, size_t prefixCharsToKeep, UniChar c, LevenshteinDFA::State & t) { auto & ps = t.m_positions; if (p.IsTransposed()) { if (p.m_offset + 2 <= m_size && m_s[p.m_offset] == c) ps.emplace_back(p.m_offset + 2, p.m_errorsLeft, false /* transposed */); return; } ASSERT(p.IsStandard(), ()); if (p.m_offset < m_size && m_s[p.m_offset] == c) { ps.emplace_back(p.m_offset + 1, p.m_errorsLeft, false /* transposed */); return; } if (p.m_errorsLeft == 0) return; if (p.m_offset < prefixCharsToKeep) return; ps.emplace_back(p.m_offset, p.m_errorsLeft - 1, false /* transposed */); if (p.m_offset == m_size) return; ps.emplace_back(p.m_offset + 1, p.m_errorsLeft - 1, false /* transposed */); size_t i; if (FindRelevant(p, c, i)) { ASSERT_GREATER(i, 0, (i)); ASSERT_LESS_OR_EQUAL(p.m_offset + i + 1, m_size, ()); ps.emplace_back(p.m_offset + i + 1, p.m_errorsLeft - i, false /* transposed */); if (i == 1) ps.emplace_back(p.m_offset, p.m_errorsLeft - 1, true /* transposed */); } }
void Point2PhantomNode::CalculateWeight(OsrmMappingTypes::FtSeg const & seg, m2::PointD const & segPt, NodeID const & nodeId, bool calcFromRight, int & weight, int & offset) const { // nodeId can be INVALID_NODE_ID when reverse node is absent. This node has no weight. if (nodeId == INVALID_NODE_ID) { offset = 0; weight = 0; return; } Index::FeaturesLoaderGuard loader(m_index, m_routingMapping.GetMwmId()); // Offset is measured in milliseconds. We don't know about speed restrictions on the road. // So we find it by a whole edge weight. // Distance from the node border to the projection point is in meters. double distanceM = 0.; // Whole node distance in meters. double fullDistanceM = 0.; // Minimal OSRM edge weight in milliseconds. EdgeWeight minWeight = 0; auto const range = m_routingMapping.m_segMapping.GetSegmentsRange(nodeId); OsrmMappingTypes::FtSeg segment; size_t const startIndex = calcFromRight ? range.second - 1 : range.first; size_t const endIndex = calcFromRight ? range.first - 1 : range.second; int const indexIncrement = calcFromRight ? -1 : 1; bool foundSeg = false; m2::PointD lastPoint; for (size_t segmentIndex = startIndex; segmentIndex != endIndex; segmentIndex += indexIncrement) { m_routingMapping.m_segMapping.GetSegmentByIndex(segmentIndex, segment); if (!segment.IsValid()) continue; FeatureType ft; loader.GetFeatureByIndex(segment.m_fid, ft); ft.ParseGeometry(FeatureType::BEST_GEOMETRY); // Find whole edge weight by node outgoing point. if (segmentIndex == range.second - 1) minWeight = GetMinNodeWeight(nodeId, ft.GetPoint(segment.m_pointEnd)); // Calculate distances. double distance = CalculateDistance(ft, segment.m_pointStart, segment.m_pointEnd); fullDistanceM += distance; if (foundSeg) continue; if (segment.m_fid == seg.m_fid && OsrmMappingTypes::IsInside(segment, seg)) { auto const splittedSegment = OsrmMappingTypes::SplitSegment(segment, seg, !calcFromRight); distanceM += CalculateDistance(ft, splittedSegment.m_pointStart, splittedSegment.m_pointEnd); // node.m_seg always forward ordered (m_pointStart < m_pointEnd) distanceM -= MercatorBounds::DistanceOnEarth( ft.GetPoint(calcFromRight ? seg.m_pointStart : seg.m_pointEnd), segPt); foundSeg = true; } else { distanceM += distance; } } ASSERT_GREATER(fullDistanceM, 0, ("No valid segments on the edge.")); double const ratio = (fullDistanceM == 0) ? 0 : distanceM / fullDistanceM; ASSERT_LESS_OR_EQUAL(ratio, 1., ()); // OSRM calculates edge weight form start to user point how offset + weight. // But it doesn't place info about start and end edge result weight into result structure. // So we store whole edge weight into offset and calculates this weights at a postprocessing step. offset = minWeight; weight = max(static_cast<int>(minWeight * ratio), 0) - minWeight; }