/// <summary> /// Encodes a bearing based on the list of coordinates and the BEARDIST parameter. /// </summary> public static float EncodeBearing(List <Coordinate> coordinates, bool startAtEnd) { if (startAtEnd) { return(BearingEncoder.EncodeBearing(new List <Coordinate>(coordinates.Reverse <Coordinate>()))); } return(BearingEncoder.EncodeBearing(coordinates)); }
/// <summary> /// Finds candidate edges starting at a given vertex matching a given fow and frc. /// </summary> public static IEnumerable <CandidatePathSegment> FindCandidatePathSegmentsFor(this Coder coder, CandidateLocation location, bool forward, FormOfWay fow, FunctionalRoadClass frc, float bearing) { var profile = coder.Profile; var relevantEdges = new List <CandidatePathSegment>(); if (location.Location.IsVertex()) { // location is a vertex, probably 99% of the time. var vertex = location.Location.VertexId(coder.Router.Db); var edgeEnumerator = coder.Router.Db.Network.GetEdgeEnumerator(vertex); foreach (var edge in edgeEnumerator) { var edgeProfile = coder.Router.Db.EdgeProfiles.Get(edge.Data.Profile); var factor = profile.Profile.Factor(edgeProfile); if (factor.Value > 0 && (factor.Direction == 0 || (forward && (factor.Direction == 1) != edge.DataInverted) || (!forward && (factor.Direction == 1) == edge.DataInverted))) { var matchScore = Score.New(Score.MATCH_ARC, "Metric indicating a match with fow, frc etc...", profile.Match(edgeProfile, fow, frc), 2); if (matchScore.Value > 0) { // ok, there is a match. // check bearing. var shape = coder.Router.Db.Network.GetShape(edge); var localBearing = BearingEncoder.EncodeBearing(shape, false); var localBearingDiff = System.Math.Abs(Extensions.AngleSmallestDifference(localBearing, bearing)); var bearingScore = Score.New(Score.BEARING_DIFF, "Bearing difference score (0=1 & 180=0)", (1f - (localBearingDiff / 180f)) * 2, 2); relevantEdges.Add(new CandidatePathSegment() { Score = location.Score * (matchScore + bearingScore), Location = location.Location, Path = new EdgePath <float>(edge.To, factor.Value * edge.Data.Distance, edge.IdDirected(), new EdgePath <float>(vertex)) }); } } } } else { // location is not a vertex but a virtual point, try available directions. var paths = location.Location.ToEdgePaths(coder.Router.Db, coder.Profile.Profile.DefaultWeightHandlerCached(coder.Router.Db), forward); var edgeEnumerator = coder.Router.Db.Network.GetEdgeEnumerator(); var locationOnNetwork = location.Location.LocationOnNetwork(coder.Router.Db); foreach (var path in paths) { if (path.From == null) { throw new Exception("An LRP was resolved while at the same time it resolved to an exact vertex."); } edgeEnumerator.MoveToEdge(path.Edge); var edge = edgeEnumerator.Current; var edgeProfile = coder.Router.Db.EdgeProfiles.Get(edge.Data.Profile); var matchScore = Score.New(Score.MATCH_ARC, "Metric indicating a match with fow, frc etc...", profile.Match(edgeProfile, fow, frc), 2); if (matchScore.Value > 0) { // ok, there is a match. // check bearing. // get shape from location -> path. var shape = location.Location.ShapePointsTo(coder.Router.Db, path.Vertex); shape.Insert(0, locationOnNetwork); shape.Add(coder.Router.Db.Network.GetVertex(path.Vertex)); var localBearing = BearingEncoder.EncodeBearing(shape, false); var localBearingDiff = System.Math.Abs(Extensions.AngleSmallestDifference(localBearing, bearing)); var bearingScore = Score.New(Score.BEARING_DIFF, "Bearing difference score (0=1 & 180=0)", (1f - (localBearingDiff / 180f)) * 2, 2); relevantEdges.Add(new CandidatePathSegment() { Score = location.Score * (matchScore + bearingScore), Location = location.Location, Path = path }); } } } return(relevantEdges); }