ftypes::HighwayClass GetOutgoingHighwayClass(NodeID outgoingNode, RoutingMapping const & routingMapping, Index const & index) { OsrmMappingTypes::FtSeg const seg = GetSegment(outgoingNode, routingMapping, GetFirstSegmentPointIndex); if (!seg.IsValid()) return ftypes::HighwayClass::Error; Index::FeaturesLoaderGuard loader(index, routingMapping.GetMwmId()); FeatureType ft; loader.GetFeatureByIndex(seg.m_fid, ft); return ftypes::GetHighwayClass(ft); }
void FindGraphNodeOffsets(uint32_t const nodeId, m2::PointD const & point, Index const * pIndex, TRoutingMappingPtr & mapping, FeatureGraphNode & graphNode) { graphNode.segmentPoint = point; helpers::Point2PhantomNode::Candidate best; auto range = mapping->m_segMapping.GetSegmentsRange(nodeId); for (size_t i = range.first; i < range.second; ++i) { OsrmMappingTypes::FtSeg s; mapping->m_segMapping.GetSegmentByIndex(i, s); if (!s.IsValid()) continue; FeatureType ft; Index::FeaturesLoaderGuard loader(*pIndex, mapping->GetMwmId()); loader.GetFeatureByIndex(s.m_fid, ft); helpers::Point2PhantomNode::Candidate mappedSeg; helpers::Point2PhantomNode::FindNearestSegment(ft, point, mappedSeg); OsrmMappingTypes::FtSeg seg; seg.m_fid = mappedSeg.m_fid; seg.m_pointStart = mappedSeg.m_segIdx; seg.m_pointEnd = mappedSeg.m_segIdx + 1; if (!s.IsIntersect(seg)) continue; if (mappedSeg.m_dist < best.m_dist) best = mappedSeg; } CHECK_NOT_EQUAL(best.m_fid, kInvalidFid, ()); graphNode.segment.m_fid = best.m_fid; graphNode.segment.m_pointStart = best.m_segIdx; graphNode.segment.m_pointEnd = best.m_segIdx + 1; }
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; }